####

Disclaimer: The purpose of the Open Case Studies project is to demonstrate the use of various data science methods, tools, and software in the context of messy, real-world data. A given case study does not cover all aspects of the research process, is not claiming to be the most appropriate way to analyze a given data set, and should not be used in the context of making policy decisions without external consultation from scientific experts.

Motivation


According to a recent report, overall tobacco use increased in youths (middle schooland high school students) in the United States in 2017 and 2018, despite previous years of declining use.

This major increase is attributed to an increase in the use of electronic cigaarette (e-cigarette) products.

E-cigarettes are referred to by many different names, including but not limited to:

  1. Electronic nicotine delivery systems (ENDS)
  2. Vapes
  3. e-hookahs
  4. vape pens
  5. tanks
  6. mods

The devices vary greatly:

[source]

See this CDC guide and the American Lung Association website for more information.

The report found that:

During 2017–2018, current use of any tobacco product increased 38.3% (from 19.6% to 27.1%) among high school students and 28.6% (from 5.6% to 7.2%) among middle school students; e-cigarette use increased 77.8% (from 11.7% to 20.8%) among high school students and 48.5% (from 3.3% to 4.9%) among middle school students.

In 2018, the Federal Drug Administration (FDA) in the United States stated that e-cigarette usage use among youth reached:

“nothing short of an epidemic proportion of growth

In this case study, we will be invistigating the same data used in the report that generated the above findings. This data comes from the The National Youth Tobacco Survey (NYTS).

Gentzke, Andrea S., Melisa Creamer, Karen A. Cullen, Bridget K. Ambrose, Gordon Willis, Ahmed Jamal, and Brian A. King. “Vital Signs: Tobacco Product Use Among Middle and High School Students - United States, 2011-2018.” MMWR. Morbidity and Mortality Weekly Report 68 (6): 157–64 (2019).

Main Questions


Our main question:

  1. How has tobacco/nicotine use by American youths changed since 2015?
  2. How do vaping rates compare between males and females?
  3. What vaping brands and flavors appear to be used the most frequently?
    We will base this on the following survey questions:
    > “During the past 30 days, what brand of e-cigarettes did you usually use?”
    >“What flavors of tobacco products have you used in the past 30 days?”

  4. Have vaping rates possibly influenced tobacco/nicotine use?

Learning Objectives


In this case study, we will cover how to import data from multiple files efficiently, how to import data from excel files, and how to make a variety of visualizations to compare multiple groups across time. We will also demonstrate how to work with codebooks. We will cover the concept of survey weighting and introduce the srvyr package. We will discuss the difference between pooled cross-sectional data and panel data. We will especially focus on using packages and functions from the Tidyverse for wrangling data, such as tidyr and dpyr and for visualization, such as as ggplot2. The tidyverse is a library of packages created by RStudio. While some students may be familiar with previous R programming packages, these packages make data science in R especially efficient.


We will begin by loading the packages that we will need:

Package Use
here to easily load and save data
readxl to import the data in the excel files
purrr to import the data in all the different excel and csv files efficiently
readr to import the CSV file data
dplyr to arrange/filter/select/compare specific subsets of the data
summarytools to get an overview of data in a different style
tidyr to rearrange data in wide and long formats

stringr | to manipulate the character strings within the data
ggplot2 | to make visualizations with multiple layers
ggpubr | to easily add regression line equations to plots
forcats | to change details about factors (categorical variables)
lmerTest| to perform linear mixed model testing
car| to perform Levene’s Test of Homogeneity of Variances
ggiraph| to make plots interactive
ggforce| to modify facets in plots
viridis| to plot in color palette
cowplot | to allow plots to be combined skimr | to get an overview of data

The first time we use a function, we will use the :: to indicate which package we are using. Unless we have overlapping function names, this is not necessary, but we will include it here to be informative about where the functions we will use come from.

Context


According to the cited Morbidity and Mortality Weekly Report this was what was already known about this topic and the implications of this study:

Importantly, the vapors used in e-cigarettes contain harmful chemicals:

E-cigarette usage has also been associated with lung injury

See here for additonal information about the potential health effects of e-cigarettes in teens and young adults.

Limitations


There are some important considerations regarding this data analysis to keep in mind:

  1. The data included in the National Youth Tobacco Survey (NYTS) does not follow the same individual students over time. A longitudinal study that does follow the same individuals over time collects data called panel data. The data in this study is called pooled [cross-sectional data]https://en.wikipedia.org/wiki/Cross-sectional_data, this data is obtained from random collection of obervations across time.

According to wikipedia: >Panel data differs from pooled cross-sectional data across time, because it deals with the observations on the same subjects in different times whereas the latter observes different subjects in different time periods

  1. The data also includes percentages of students that reported use of particular tobacco product, but the survey questions did not ask how much uses of one product compared to another - for example the survey asked questions like:“What flavors of tobacco products have you used in the past 30 days?” Thus, it is unclear how often one flavor was used by the same individual over another.

While gender and sex are not actually binary, the dataused in this analysis only contains information for groups of individuals who answered the survey questions as male or female.

What are the data?


The data in this case study comes from the National Youth Tobacco Survey (NYTS) which is an annual survey that asks students in high school and middle school (grades 6-12) about tobacco usage in the United States of America.

The data for this survey is freely available online at this website with data from 1999, 2000, 2002, 2004, 2006, 2009, and 2011-2019. We will be using data from 2015-2019 due to the fact that these years are the most recent that asked questions recarding e-cigarette usage.

Each year includes documentation, such as a codebook and an excel file containing the data:

Therefore, since we are using data from 2015-2019, the data we are interested in is located in 5 different excel files, each with their own codebook.

The codebook contains information describing the data within the excel file.

As you can see the excel file contains very short variable names and values, and it is not clear what they mean without the codebook:

The codebook explains what the variables (the columns) are:

And the codebook explains what the values for each variable are:

We will explain more later about what the values on the right indicate.

The reason that there are codebooks for each year is because the questions asked year varied slightly.

The data in this survey is what is called pooled cross-sectional data. In otherwords, different subsets of students are surveyed each year and it is not clear which, if any , individuals particpate from one year to the next.

Data Import


Reading in the excel files


Since these excel files are so large (each has roughly 20,000 rows), it takes a bit of time for the data to load. To make the process faster, we previously imported these files, selected only our questions of interest, and saved this data as csv files.

Click here for details on how the data was originally imported

First we created a list of filenames of all the different excel files. Using the here() function of the here package, we looked in all the directories of the project. The list.files() function looked for all files with .xlsx within these subdirectories.

[1] "docs/2015-nyts-dataset-and-codebook-microsoft-excel/nyts2015.xlsx"
[2] "docs/2016-nyts-dataset-and-codebook-microsoft-excel/nyts2016.xlsx"
[3] "docs/2017-nyts-dataset-and-codebook-microsoft-excel/nyts2017.xlsx"
[4] "docs/2018-nyts-dataset-and-codebook-microsoft-excel/nyts2018.xlsx"
[5] "docs/2019-nyts-dataset-and-codebook-microsoft-excel/nyts2019.xlsx"

All the files were read using read_excel() of the readxl package. Using the map() function of the purrr package this was done efficiently for all of the excel files in the list using one command. The . is used to indicate that we want to apply the read_excel() function to the data that we just piped into the map() function.

Here will also used the %>% pipe which can be used to define the input for later sequential steps.

This created a single list of tibbles (one for each file).

Each excel file name was extracted using the str_extract() function of the stringr package. Here we are keeping occurances of the character string “nyts201” followed by a “5”,“6”,“7”,“8”, or “9”.

[1] "nyts2015" "nyts2016" "nyts2017" "nyts2018" "nyts2019"

These names became the names of the tibbles in the list of tibbles.

Specific columns were selected from each of the tibbles using the varaible name, as identified in the codebook for being of interest. In some cases functions like starts_with() of the dplyr package were used to select several variables. Most of the survey questions about tobacco use start with an "E" or a "C" according to the codebooks.

tbl_files[["nyts2015"]] <- tbl_files[["nyts2015"]] %>%
    dplyr::select(psu, #Primary Sampling Unit
                  finwgt,#Analysis Weight
                  stratum,#Sampling stratum
                  Qn1, #Age
                  Qn2, #Sex
                  Qn3, #Grade
                  starts_with("E",
                              ignore.case = FALSE),
                  starts_with("C",
                              ignore.case = FALSE),
                  )


tbl_files[["nyts2016"]] <- tbl_files[["nyts2016"]] %>%
    dplyr::select(psu,
                  finwgt,
                  stratum,
                  Q1, #Age
                  Q2, #Sex
                  Q3, #Grade
                  starts_with("E",
                              ignore.case = FALSE),
                  starts_with("C",
                              ignore.case = FALSE),
                  Q50A, #Menthol # What flavors of tobacco products have you used in the past 30 days? (Select one or more)
                  Q50B, #Clove or spice
                  Q50C, #Fruit
                  Q50D, #Chocolate
                  Q50E, #Alcoholic Drink
                  Q50F, #Candy/Desserts/Other Sweets
                  Q50G, #Some Other Flavor Not Listed Here
                  Q50H #I Did Not Use Flavored Tobacco Products In the Past
                  ) 

tbl_files[["nyts2017"]] <- tbl_files[["nyts2017"]] %>%
    dplyr::select(psu,
                  finwgt,
                  stratum,
                  Q1, #Age
                  Q2, #Sex
                  Q3, #Grade
                  starts_with("E",
                              ignore.case = FALSE),
                  starts_with("C",
                              ignore.case = FALSE),
                  Q50A, #Menthol # What flavors of tobacco products have you used in the past 30 days? (Select one or more)
                  Q50B, #Clove or spice
                  Q50C, #Fruit
                  Q50D, #Chocolate
                  Q50E, #Alcoholic Drink
                  Q50F, #Candy/Desserts/Other Sweets
                  Q50G, #Some Other Flavor Not Listed Here
                  Q50H #I Did Not Use Flavored Tobacco Products In the Past
                  )

tbl_files[["nyts2018"]] <- tbl_files[["nyts2018"]] %>%
    dplyr::select(psu,
                  finwgt,
                  stratum,
                  Q1, #Age
                  Q2, #Sex
                  Q3, #Grade
                  starts_with("E",
                              ignore.case = FALSE),
                  starts_with("C",
                              ignore.case = FALSE),
                  Q50A, #Menthol # What flavors of tobacco products have you used in the past 30 days? (Select one or more)
                  Q50B, #Clove or spice
                  Q50C, #Fruit
                  Q50D, #Chocolate
                  Q50E, #Alcoholic Drink
                  Q50F, #Candy/Desserts/Other Sweets
                  Q50G, #Some Other Flavor Not Listed Here
                  Q50H #I Did Not Use Flavored Tobacco Products In the Past
                  )

tbl_files[["nyts2019"]] <- tbl_files[["nyts2019"]] %>%
    dplyr::select(psu,
                  finwgt,
                  stratum,
                  Q1, #Age
                  Q2, #Sex
                  Q3, #Grade
                  starts_with("E",
                              ignore.case = FALSE),
                  starts_with("C",
                              ignore.case = FALSE),
                  Q40, #Brand, e-cigarettes
                  Q62A, #Menthol # What flavors of tobacco products have you used in the past 30 days? (Select one or more)
                  Q62B, #Clove or spice
                  Q62C, #Fruit 
                  Q62D, #Chocolate
                  Q62E, #Alcoholic Drink
                  Q62F, #Candy/Desserts/Other Sweets
                  Q62G, #Some Other Flavor Not Listed Here 
                  )

A directory was created using the base dir.create() function called data_reduced for the csv files. New csv files were created for each of the tbls in the list using the write_csv() function of the readr package. This was done all at once using the base mappy() function.

Now we will show how to read in the data from the five csv files that were created from the five different excel files.

Data Exploration and Wrangling


Renaming variables


Here is what the data for 2015 looks like:

Rows: 17,711
Columns: 29
$ psu        <chr> "015438", "015438", "015438", "015438", "015438", "015438"…
$ finwgt     <dbl> 216.7268, 324.9620, 324.9620, 397.1552, 264.8745, 264.8745…
$ stratum    <chr> "BR3", "BR3", "BR3", "BR3", "BR3", "BR3", "BR3", "BR3", "B…
$ Qn1        <dbl> 10, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,…
$ Qn2        <dbl> 2, 1, 1, 1, 2, 2, 1, 2, 1, 2, 2, 2, 1, 2, 2, 1, 2, 2, 2, 2…
$ Qn3        <dbl> 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 5…
$ ECIGT      <dbl> 2, 1, 2, 1, 2, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1…
$ ECIGAR     <dbl> 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2…
$ ESLT       <dbl> 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ EELCIGT    <dbl> 2, 1, 2, 1, 2, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 1…
$ EROLLCIGTS <dbl> 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2…
$ EFLAVCIGTS <dbl> 2, 2, 2, 1, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ EBIDIS     <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ EFLAVCIGAR <dbl> 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 2…
$ EHOOKAH    <dbl> 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ EPIPE      <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ ESNUS      <dbl> 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ EDISSOLV   <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ CCIGT      <dbl> 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ CCIGAR     <dbl> 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ CSLT       <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ CELCIGT    <dbl> 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ CROLLCIGTS <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ CFLAVCIGTS <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ CBIDIS     <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ CHOOKAH    <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ CPIPE      <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ CSNUS      <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ CDISSOLV   <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…

Currently, it isn’t very clear what most of the variables indicate.

We want to rename variables like Qn1 to something more meaningful like Age.

To do this we will use the rename() function of the dplyr package. The new name is always listed first before the =.

We also want to update the values for age and grade, so that they are more understandable.

Recall from the codebook for this year, that age isn’t listed in the way one might expect:

The same is true for grade:

This is why it is so important to always check the codebook!!

We also need to add new variables about usage of brands and specific flavors of e-cigrattes, because although later years have questions about this, this year unfortunately only has broad questions about flavors. Eventually we want to put the data from each year together, so we need the same variables for each year. Thus we need to add variables that just say NA for the brand and flavor data for this year.

To change the existing variables and create new variabels, we will use the mutate function of the dplyr package.

Now we can see how the data has changed:

Rows: 17,711
Columns: 38
$ psu                  <chr> "015438", "015438", "015438", "015438", "015438"…
$ finwgt               <dbl> 216.7268, 324.9620, 324.9620, 397.1552, 264.8745…
$ stratum              <chr> "BR3", "BR3", "BR3", "BR3", "BR3", "BR3", "BR3",…
$ Age                  <dbl> 10, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1…
$ Sex                  <dbl> 2, 1, 1, 1, 2, 2, 1, 2, 1, 2, 2, 2, 1, 2, 2, 1, …
$ Grade                <dbl> 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, …
$ ECIGT                <dbl> 2, 1, 2, 1, 2, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 1, …
$ ECIGAR               <dbl> 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ ESLT                 <dbl> 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, …
$ EELCIGT              <dbl> 2, 1, 2, 1, 2, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1, …
$ EROLLCIGTS           <dbl> 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, …
$ EFLAVCIGTS           <dbl> 2, 2, 2, 1, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ EBIDIS               <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ EFLAVCIGAR           <dbl> 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, …
$ EHOOKAH              <dbl> 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, …
$ EPIPE                <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ ESNUS                <dbl> 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ EDISSOLV             <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ CCIGT                <dbl> 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ CCIGAR               <dbl> 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ CSLT                 <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ CELCIGT              <dbl> 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ CROLLCIGTS           <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ CFLAVCIGTS           <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ CBIDIS               <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ CHOOKAH              <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ CPIPE                <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ CSNUS                <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ CDISSOLV             <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ brand_ecig           <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ menthol              <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ clove_spice          <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ fruit                <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ chocolate            <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ alcoholic_drink      <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ candy_dessert_sweets <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ other                <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ no_use               <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …

Updating Values

We also want to replace the value of 19 for Age to be ">18" and the value of 13 for Grade to be replaced with "Ungraded/Other" Also accroding to the codebooks, numeric values of 1 indicate a survey answer of FALSE, while a value of 2 indicates TRUE. Sex needs to be recoded, but it is a bit unclear if it is encoded slightly differently across years.

Let’s create a function to make all these updates except for Sex:

Now let’s update the Sex encoding:

It’s a bit difficult to tell if the encoding was the same across years, so let’s check using the count() function of the dplyr package.

According to the codebook, we should have:
1) 8,958 males in 2015 2) 10,438 males in 2016 3) 8,881 males in 2017
4) 10,069 males in 2018
5) 9,803 males in 2019

$nyts2015
# A tibble: 3 x 2
    Sex     n
  <dbl> <int>
1     1  8958
2     2  8622
3    NA   131

$nyts2016
# A tibble: 3 x 2
    Sex     n
  <dbl> <int>
1     1 10438
2     2 10082
3    NA   155

$nyts2017
# A tibble: 3 x 2
    Sex     n
  <dbl> <int>
1     1  8881
2     2  8815
3    NA   176

$nyts2018
# A tibble: 3 x 2
    Sex     n
  <dbl> <int>
1     1 10069
2     2  9920
3    NA   200

$nyts2019
# A tibble: 3 x 2
  Sex       n
  <chr> <int>
1 .N      116
2 1      9803
3 2      9099

Thus, it looks like males were encoded as 1 for each year.

  1. 8,958 males in 2015 where 1 = male
  2. 10,438 males in 2016 where 1 = male
  3. 8,881 males in 2017 where 1 = male
  4. 10,069 males in 2018 where 1 = male
  5. 9,803 males in 2019 where 1 = male
$nyts2015
# A tibble: 3 x 2
  Sex        n
  <fct>  <int>
1 male    8958
2 female  8622
3 <NA>     131

$nyts2016
# A tibble: 3 x 2
  Sex        n
  <fct>  <int>
1 male   10438
2 female 10082
3 <NA>     155

$nyts2017
# A tibble: 3 x 2
  Sex        n
  <fct>  <int>
1 male    8881
2 female  8815
3 <NA>     176

$nyts2018
# A tibble: 3 x 2
  Sex        n
  <fct>  <int>
1 male   10069
2 female  9920
3 <NA>     200

$nyts2019
# A tibble: 3 x 2
  Sex        n
  <fct>  <int>
1 .N       116
2 male    9803
3 female  9099

Looks good!

The years (2016-2019) that have flavors also need the flavor data to be logical:

Now there are just a few changes needed that are specific to 2019:

Great! Now we have all the same variables and our values don’t need to be handled any differently for any of the years. Thus we can combine the data across years.

# A tibble: 6 x 41
  year  psu   finwgt stratum Age   Sex   Grade ECIGT ECIGAR ESLT  EELCIGT
  <chr> <chr>  <dbl> <chr>   <fct> <fct> <fct> <lgl> <lgl>  <lgl> <lgl>  
1 nyts… 0154…   217. BR3     18    fema… 12    FALSE TRUE   FALSE FALSE  
2 nyts… 0154…   325. BR3     17    male  12    TRUE  TRUE   FALSE TRUE   
3 nyts… 0154…   325. BR3     18    male  12    FALSE FALSE  FALSE FALSE  
4 nyts… 0154…   397. BR3     18    male  12    TRUE  FALSE  FALSE TRUE   
5 nyts… 0154…   265. BR3     18    fema… 12    FALSE FALSE  FALSE FALSE  
6 nyts… 0154…   265. BR3     18    fema… 12    TRUE  FALSE  FALSE TRUE   
# … with 30 more variables: EROLLCIGTS <lgl>, EFLAVCIGTS <lgl>, EBIDIS <lgl>,
#   EFLAVCIGAR <lgl>, EHOOKAH <lgl>, EPIPE <lgl>, ESNUS <lgl>, EDISSOLV <lgl>,
#   CCIGT <lgl>, CCIGAR <lgl>, CSLT <lgl>, CELCIGT <lgl>, CROLLCIGTS <lgl>,
#   CFLAVCIGTS <lgl>, CBIDIS <lgl>, CHOOKAH <lgl>, CPIPE <lgl>, CSNUS <lgl>,
#   CDISSOLV <lgl>, brand_ecig <chr>, menthol <lgl>, clove_spice <lgl>,
#   fruit <lgl>, chocolate <lgl>, alcoholic_drink <lgl>,
#   candy_dessert_sweets <lgl>, other <lgl>, no_use <lgl>, EHTP <lgl>,
#   CHTP <lgl>

Looks like we just need to remove "nyts" from the year variable that we created from the names of the tibbles in our list.

Here is our clean and wrangled data:

# A tibble: 6 x 41
   year psu   finwgt stratum Age   Sex   Grade ECIGT ECIGAR ESLT  EELCIGT
  <dbl> <chr>  <dbl> <chr>   <fct> <fct> <fct> <lgl> <lgl>  <lgl> <lgl>  
1  2015 0154…   217. BR3     18    fema… 12    FALSE TRUE   FALSE FALSE  
2  2015 0154…   325. BR3     17    male  12    TRUE  TRUE   FALSE TRUE   
3  2015 0154…   325. BR3     18    male  12    FALSE FALSE  FALSE FALSE  
4  2015 0154…   397. BR3     18    male  12    TRUE  FALSE  FALSE TRUE   
5  2015 0154…   265. BR3     18    fema… 12    FALSE FALSE  FALSE FALSE  
6  2015 0154…   265. BR3     18    fema… 12    TRUE  FALSE  FALSE TRUE   
# … with 30 more variables: EROLLCIGTS <lgl>, EFLAVCIGTS <lgl>, EBIDIS <lgl>,
#   EFLAVCIGAR <lgl>, EHOOKAH <lgl>, EPIPE <lgl>, ESNUS <lgl>, EDISSOLV <lgl>,
#   CCIGT <lgl>, CCIGAR <lgl>, CSLT <lgl>, CELCIGT <lgl>, CROLLCIGTS <lgl>,
#   CFLAVCIGTS <lgl>, CBIDIS <lgl>, CHOOKAH <lgl>, CPIPE <lgl>, CSNUS <lgl>,
#   CDISSOLV <lgl>, brand_ecig <chr>, menthol <lgl>, clove_spice <lgl>,
#   fruit <lgl>, chocolate <lgl>, alcoholic_drink <lgl>,
#   candy_dessert_sweets <lgl>, other <lgl>, no_use <lgl>, EHTP <lgl>,
#   CHTP <lgl>

Reminder: Current users are a subset of ever users.

Data Visualization


Question 1

For lots of pivot_longer() that are the same… can use pivot_longer_spec()

spec <- relig_income %>% build_longer_spec( cols = -religion, names_to = “income”, values_to = “count” ) pivot_longer_spec(relig_income, spec)

But need to decide if we are going to create some new data frames…

Question 3

What vaping brands and flavors appear to be used the most frequently?

Huang J, Duan Z, Kwok J, et al. Tob Control 2019;28:146–151.

Huang J, Duan Z, Kwok J, et al. Tob Control 2019;28:146–151.

Paper

plot5 <- nyts_data %>%
  filter(year!=2015) %>%
  filter(menthol==TRUE|
           clove_spice==TRUE|
           fruit==TRUE|
           chocolate==TRUE|
           alcoholic_drink==TRUE|
           candy_dessert_sweets==TRUE|
           other==TRUE) %>%
  mutate(ecig_sum_ever = select(., EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           ecig_sum_current = select(., CELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               select(.,-EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               select(.,-CELCIGT) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(ecig_ever = case_when(ecig_sum_ever > 0 ~ TRUE,
                                    ecig_sum_ever ==0 ~ FALSE),
           ecig_current = case_when(ecig_sum_current > 0 ~ TRUE,
                                    ecig_sum_current ==0 ~ FALSE),
           non_ecig_ever = case_when(non_ecig_sum_ever > 0 ~ TRUE,
                                    non_ecig_sum_ever ==0 ~ FALSE),
           non_ecig_current = case_when(non_ecig_sum_current > 0 ~ TRUE,
                                    non_ecig_sum_current ==0 ~ FALSE)) %>%
  mutate(ecig_only_ever = case_when(ecig_ever == TRUE &
                                      non_ecig_ever ==FALSE ~ TRUE,
                                    TRUE ~ FALSE),
           ecig_only_current = case_when(ecig_current == TRUE &
                                           non_ecig_ever ==FALSE ~ TRUE,
                                    TRUE ~ FALSE),
           non_ecig_only_ever = case_when(non_ecig_ever == TRUE &
                                            ecig_ever ==FALSE ~ TRUE,
                                    TRUE ~ FALSE),
           non_ecig_only_current = case_when(non_ecig_current == TRUE &
                                               ecig_ever ==FALSE ~ TRUE,
                                    TRUE ~ FALSE)) %>%
  mutate(Group = case_when(ecig_only_ever==TRUE |
                             ecig_only_current==TRUE ~ "Only e-cigarettes",
                         non_ecig_only_ever==TRUE |
                           non_ecig_only_current==TRUE ~ "Only other products",
                                    TRUE ~ "Both")) %>%
  filter(Group!="Both") %>%
  group_by(year, Group) %>%
  summarise(`Menthol`=(sum(menthol, na.rm = TRUE)*100)/
              sum(!is.na(menthol)),
              `Clove or Spice`=(sum(clove_spice, na.rm = TRUE)*100)/
              sum(!is.na(clove_spice)),
              `Fruit`=(sum(fruit, na.rm = TRUE)*100)/sum(!is.na(fruit)),
              `Chocolate`=(sum(chocolate, na.rm = TRUE)*100)/
              sum(!is.na(chocolate)),
              `Alcoholic Drink`=(sum(alcoholic_drink, na.rm = TRUE)*100)/
              sum(!is.na(alcoholic_drink)),
              `Candy/Desserts/Sweets`=(sum(candy_dessert_sweets, na.rm = TRUE)*100)/
              sum(!is.na(candy_dessert_sweets)),
            `Other`=(sum(other, na.rm = TRUE)*100)/
              sum(!is.na(other)),
            Respondents=n()) %>%
  #converting all columns between and including Menthol and Other to one column called Flavor
  pivot_longer(cols = Menthol:Other, names_to = "Flavor", values_to = "Percentage of students") %>%
  filter(!is.na(`Percentage of students`),
         Flavor!="Other") %>%
  group_by(Flavor) %>%
  mutate(affirmative=(Respondents * `Percentage of students`)/100) %>%
  mutate(flavor_mean = sum(affirmative)/sum(Respondents)) %>%
  ungroup() %>%
  mutate(flavor_mean_rank = dense_rank(flavor_mean),
         Flavor = fct_reorder(Flavor, flavor_mean_rank)) %>%
  ggplot(aes(x=year, y=`Percentage of students`, color=Group)) +
  facet_wrap(.~Flavor,ncol=3) +
  geom_line() + 
  geom_point(show.legend = FALSE) + 
  theme_minimal() +
  theme(legend.position = "bottom",
          axis.title.x = element_blank(),
        axis.text.x = element_text(angle = 90)) + 
  labs(title = "Among users of only one type of product, what vaping flavors appear to be used the most frequently?",
       subtitle = "Percent reporting only e-cigarette use vs only other nicotine product use")

plot5

Question 4

Have vaping rates possibly influenced tobacco/nicotine use?

plot7 <- nyts_data %>%
    mutate(ecig_sum_ever = select(., EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           ecig_sum_current = select(., CELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               select(.,-EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               select(.,-CELCIGT) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(ecig_ever = case_when(ecig_sum_ever > 0 ~ TRUE,
                                    ecig_sum_ever ==0 ~ FALSE),
           ecig_current = case_when(ecig_sum_current > 0 ~ TRUE,
                                    ecig_sum_current ==0 ~ FALSE),
           non_ecig_ever = case_when(non_ecig_sum_ever > 0 ~ TRUE,
                                    non_ecig_sum_ever ==0 ~ FALSE),
           non_ecig_current = case_when(non_ecig_sum_current > 0 ~ TRUE,
                                    non_ecig_sum_current ==0 ~ FALSE)) %>%
    group_by(year) %>%
    summarise(ecig_ever_year=(sum(ecig_ever, na.rm = TRUE)*100)/
                sum(!is.na(ecig_ever)),
              ecig_current_year=(sum(ecig_current, na.rm = TRUE)*100)/
                sum(!is.na(ecig_current)),
              non_ecig_ever_year=(sum(non_ecig_ever, na.rm = TRUE)*100)/
                sum(!is.na(non_ecig_ever)),
              non_ecig_current_year=(sum(non_ecig_current, na.rm = TRUE)*100)/
                sum(!is.na(non_ecig_current))) %>%
    pivot_longer(cols = -year, names_to = "Category", values_to = "Percentage of students") %>%
    mutate(User = case_when(Category =="ecig_ever_year" ~ "Ever",
                           Category =="non_ecig_ever_year" ~ "Ever",
                           Category =="ecig_current_year" ~ "Current",
                           Category =="non_ecig_current_year" ~ "Current")) %>%
    mutate(Product = case_when(Category =="ecig_ever_year" ~ "E-cigarettes",
                           Category =="non_ecig_ever_year" ~ "Other products",
                           Category =="ecig_current_year" ~ "E-cigarettes",
                           Category =="non_ecig_current_year" ~ "Other products")) %>%
    filter(User=="Ever") %>%
    ggplot(aes(x=year,y=`Percentage of students`, color=Product)) +
    geom_line(linetype=1) + # geom_bar(stat="identity", position = "dodge", color="black") +
  geom_point(show.legend = FALSE) +
  scale_y_continuous(breaks = seq(10, 60, by = 10), limits = c(10,60)) +
    theme_minimal() +
    theme(legend.position = "bottom",
          axis.title.x = element_blank()) +
    labs(title = "How does e-cigarette ever use compare to ever use of other products over the years?",
         subtitle = "E-cigarette and non-e-cigarette use",
         y = "% of students")

plot7

plot8 <- nyts_data %>%
    mutate(ecig_sum_ever = select(., EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           ecig_sum_current = select(., CELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               select(.,-EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               select(.,-CELCIGT) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(ecig_ever = case_when(ecig_sum_ever > 0 ~ TRUE,
                                    ecig_sum_ever ==0 ~ FALSE),
           ecig_current = case_when(ecig_sum_current > 0 ~ TRUE,
                                    ecig_sum_current ==0 ~ FALSE),
           non_ecig_ever = case_when(non_ecig_sum_ever > 0 ~ TRUE,
                                    non_ecig_sum_ever ==0 ~ FALSE),
           non_ecig_current = case_when(non_ecig_sum_current > 0 ~ TRUE,
                                    non_ecig_sum_current ==0 ~ FALSE)) %>%
    group_by(year) %>%
    summarise(ecig_ever_year=(sum(ecig_ever, na.rm = TRUE)*100)/
                sum(!is.na(ecig_ever)),
              ecig_current_year=(sum(ecig_current, na.rm = TRUE)*100)/
                sum(!is.na(ecig_current)),
              non_ecig_ever_year=(sum(non_ecig_ever, na.rm = TRUE)*100)/
                sum(!is.na(non_ecig_ever)),
              non_ecig_current_year=(sum(non_ecig_current, na.rm = TRUE)*100)/
                sum(!is.na(non_ecig_current))) %>%
    pivot_longer(cols = -year, names_to = "Category", values_to = "Percentage of students") %>%
    # gather(key=Category,
    #        value=`Percentage of students`,
    #        -year) %>%
    mutate(User = case_when(Category =="ecig_ever_year" ~ "Ever",
                           Category =="non_ecig_ever_year" ~ "Ever",
                           Category =="ecig_current_year" ~ "Current",
                           Category =="non_ecig_current_year" ~ "Current")) %>%
    mutate(Product = case_when(Category =="ecig_ever_year" ~ "E-cigarettes",
                           Category =="non_ecig_ever_year" ~ "Other products",
                           Category =="ecig_current_year" ~ "E-cigarettes",
                           Category =="non_ecig_current_year" ~ "Other products")) %>%
    ggplot(aes(x=year,y=`Percentage of students`, color=Product, linetype=User)) +
    geom_line() +
  geom_point(show.legend = FALSE) +
  scale_linetype_manual(values = c(2,1)) +
  scale_y_continuous(breaks = seq(0, 60, by = 10), limits = c(0,60)) +
    theme_minimal() +
    theme(legend.position = "bottom",
          axis.title.x = element_blank()) +
    labs(title = "How does e-cigarette use compare to use of other products over the years?",
         subtitle = "E-cigarette and non-e-cigarette use",
         y = "% of students")

plot8

Weighted Sample

plotA_w <- nyts_data %>%
    mutate(tobacco_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               apply(1, sum, na.rm=TRUE),
           tobacco_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(tobacco_ever = case_when(tobacco_sum_ever > 0 ~ TRUE,
                                    tobacco_sum_ever ==0 ~ FALSE),
           tobacco_current = case_when(tobacco_sum_current > 0 ~ TRUE,
                                    tobacco_sum_current ==0 ~ FALSE)) %>%
  as_survey_design(strata = stratum, ids = psu, weight  = finwgt, nest=TRUE) %>%
    group_by(year) %>%
  summarise(tobacco_ever_year = survey_mean(tobacco_ever, vartype = "ci", na.rm=TRUE),
            tobacco_current_year = survey_mean(tobacco_current, vartype = "ci", na.rm=TRUE))  %>%
  mutate_at(vars(-year), "*", 100) %>%
    pivot_longer(cols = -year, names_to = "Type", values_to = "Percentage of students") %>%
    # gather(key=Type,
    #        value=`Percentage of students`,
    #        -year) %>%
  mutate(Estimate = case_when(grepl("_low", Type) ~ "Lower",
                          grepl("_upp", Type) ~ "Upper",
                          TRUE ~ "Mean"),
         User = case_when(grepl("ever", Type) ~ "Ever",
                          grepl("current", Type) ~ "Current",
                          TRUE ~ "Mean")) %>%
  dplyr::select(-Type) %>%
  pivot_wider(names_from = Estimate, 
              values_from = `Percentage of students`) %>%
  #spread(Estimate, `Percentage of students`) %>%
  ggplot(aes(x=year,y=Mean)) +
  geom_line(aes(linetype=User)) +
  geom_linerange(aes(ymin = Lower, ymax = Upper), show.legend = FALSE) +
  scale_linetype_manual(values = c(2,1)) +
    scale_y_continuous(breaks = seq(0,70,by=10),
                       labels = seq(0,70,by=10),
                       limits = c(0,70)) +
    theme_minimal() +
    theme(legend.position = "none",
          axis.title.x = element_blank()) +
    labs(title = "Nicotine product users more prevalent after 2017",
         y = "% of students")

plotB_w <- nyts_data %>%
    mutate(ecig_sum_ever = select(., EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           ecig_sum_current = select(., CELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               select(.,-EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               select(.,-CELCIGT) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(ecig_ever = case_when(ecig_sum_ever > 0 ~ TRUE,
                                    ecig_sum_ever ==0 ~ FALSE),
           ecig_current = case_when(ecig_sum_current > 0 ~ TRUE,
                                    ecig_sum_current ==0 ~ FALSE),
           non_ecig_ever = case_when(non_ecig_sum_ever > 0 ~ TRUE,
                                    non_ecig_sum_ever ==0 ~ FALSE),
           non_ecig_current = case_when(non_ecig_sum_current > 0 ~ TRUE,
                                    non_ecig_sum_current ==0 ~ FALSE)) %>%
  as_survey_design(strata = stratum, ids = psu, weight  = finwgt, nest=TRUE) %>%
    group_by(year) %>%
    summarise(ecig_ever_year = survey_mean(ecig_ever, vartype = "ci", na.rm=TRUE),
            ecig_current_year = survey_mean(ecig_current, vartype = "ci", na.rm=TRUE),
            non_ecig_ever_year = survey_mean(non_ecig_ever, vartype = "ci", na.rm=TRUE),
            non_ecig_current_year = survey_mean(non_ecig_current, vartype = "ci", na.rm=TRUE)) %>%
  mutate_at(vars(-year), "*", 100) %>%
  dplyr::select(year,
                ecig_ever_year,
                ecig_current_year,
                non_ecig_ever_year,
                non_ecig_current_year,
                contains("low"),
                contains("upp")) %>%
  pivot_longer(cols = -year, names_to = "Category", values_to = "Percentage of students") %>%
    # gather(key=Category,
    #        value=`Percentage of students`,
    #        -year)  %>%
  mutate(Estimate = case_when(grepl("_low", Category) ~ "Lower",
                          grepl("_upp", Category) ~ "Upper",
                          TRUE ~ "Mean"),
         User = case_when(grepl("current", Category) ~ "Current",
                          TRUE ~ "Ever",),
         Product = case_when(grepl("non_ecig", Category) ~ "Other products",
                          TRUE ~ "E-cigarettes")) %>%
  dplyr::select(-Category) %>%
  pivot_wider(names_from = Estimate, 
              values_from = `Percentage of students`) %>%
  #spread(Estimate, `Percentage of students`) %>%
  filter(User=="Ever") %>%
  dplyr::rename("Lower_temp" = Upper,
                "Upper_temp" = Lower) %>%
  dplyr::rename("Lower"=Lower_temp,
                "Upper"=Upper_temp) %>%
    ggplot(aes(x=year,y=Mean, color=Product)) +
  geom_line(linetype=1) +
  geom_linerange(aes(ymin = Lower, ymax = Upper), show.legend = FALSE) +
  scale_y_continuous(breaks = seq(10, 60, by = 10), limits = c(10,60)) +
    theme_minimal() +
    theme(legend.position = "none",
          axis.title.x = element_blank()) +
    labs(title = "% ever trying e-cigarettes increases &\n% ever trying other products decreases",
         y = "% of students")

#### the wrangling looks the same as the above plot...
plotC_w <- nyts_data %>%
    mutate(ecig_sum_ever = select(., EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           ecig_sum_current = select(., CELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               select(.,-EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               select(.,-CELCIGT) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(ecig_ever = case_when(ecig_sum_ever > 0 ~ TRUE,
                                    ecig_sum_ever ==0 ~ FALSE),
           ecig_current = case_when(ecig_sum_current > 0 ~ TRUE,
                                    ecig_sum_current ==0 ~ FALSE),
           non_ecig_ever = case_when(non_ecig_sum_ever > 0 ~ TRUE,
                                    non_ecig_sum_ever ==0 ~ FALSE),
           non_ecig_current = case_when(non_ecig_sum_current > 0 ~ TRUE,
                                    non_ecig_sum_current ==0 ~ FALSE)) %>%
  as_survey_design(strata = stratum, ids = psu, weight  = finwgt, nest=TRUE) %>%
    group_by(year) %>%
  summarise(ecig_ever_year = survey_mean(ecig_ever, vartype = "ci", na.rm=TRUE),
            ecig_current_year = survey_mean(ecig_current, vartype = "ci", na.rm=TRUE),
            non_ecig_ever_year = survey_mean(non_ecig_ever, vartype = "ci", na.rm=TRUE),
            non_ecig_current_year = survey_mean(non_ecig_current, vartype = "ci", na.rm=TRUE)) %>%
  mutate_at(vars(-year), "*", 100) %>%
  dplyr::select(year,
                ecig_ever_year,
                ecig_current_year,
                non_ecig_ever_year,
                non_ecig_current_year,
                contains("low"),
                contains("upp")) %>%
  pivot_longer(cols = -year, names_to = "Category", values_to = "Percentage of students") %>%
    # gather(key=Category,
    #        value=`Percentage of students`,
    #        -year) %>%
    mutate(Estimate = case_when(grepl("_low", Category) ~ "Lower",
                          grepl("_upp", Category) ~ "Upper",
                          TRUE ~ "Mean"),
         User = case_when(grepl("ever", Category) ~ "Ever",
                          grepl("current", Category) ~ "Current"),
         Product = case_when(grepl("non_ecig", Category) ~ "Other products",
                          TRUE ~ "E-cigarettes")) %>%
  dplyr::select(-Category) %>%
  pivot_wider(names_from = Estimate, 
              values_from = `Percentage of students`) %>%
  #spread(Estimate, `Percentage of students`) %>%
    ggplot(aes(x=year,y=Mean, color=Product)) +
  geom_line(aes(linetype=User)) +
  geom_linerange(aes(ymin = Lower, ymax = Upper), show.legend = FALSE) +
  scale_linetype_manual(values = c(2,1)) +
  scale_y_continuous(breaks = seq(0, 60, by = 10), limits = c(0,60)) +
    theme_minimal() +
    theme(legend.position = "none",
          axis.title.x = element_blank()) +
    labs(title = "% Using e-cigarettes increases &\n% using Other products decreases",
         y = "% of students")

title_w <- ggdraw() + 
  draw_label(
    expression("Have vaping rates possibly influenced tobacco/nicotine use?"),
    fontface = 'bold',
    size=14,
    x = 0,
    hjust = 0
  ) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

plotsA_w <- plot_grid(plotA_w,
                     rel_widths = c(1),
                     align = "v",
                     axis = "bt")
plotsBC_w <- plot_grid(plotB_w,
                     plotC_w,
                     rel_widths = c(1,1),
                     align = "v",
                     axis = "bt")

legend_w <- get_legend(plotB_w +
                       theme(legend.position = "bottom",
                             legend.direction = "horizontal"))

figure_w <- plot_grid(title_w,
                      plotsA_w,
                      plotsBC_w,
                      legend_w,
                      ncol = 1,
                      rel_heights = c(0.1,
                                      1,
                                      1,
                                      0.1),
                      scale = 1.0)

figure_w

Hypothethical Cohort

plotA_w_8 <- nyts_data %>%
  filter((Grade == "8" & year == 2015) |
         (Grade == "9" & year == 2016) |
         (Grade == "10" & year == 2017) |
         (Grade == "11" & year == 2018) |
          (Grade == "12" & year == 2019) 
         ) %>%
    mutate(tobacco_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               apply(1, sum, na.rm=TRUE),
           tobacco_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(tobacco_ever = case_when(tobacco_sum_ever > 0 ~ TRUE,
                                    tobacco_sum_ever ==0 ~ FALSE),
           tobacco_current = case_when(tobacco_sum_current > 0 ~ TRUE,
                                    tobacco_sum_current ==0 ~ FALSE)) %>%
  as_survey_design(strata = stratum, ids = psu, weight  = finwgt) %>%
    group_by(year) %>%
  summarise(tobacco_ever_year = survey_mean(tobacco_ever, vartype = "ci", na.rm=TRUE),
            tobacco_current_year = survey_mean(tobacco_current, vartype = "ci", na.rm=TRUE))  %>%
  mutate_at(vars(-year), "*", 100) %>%
    pivot_longer(cols = -year, names_to = "Type", values_to = "Percentage of students")%>%
    # gather(key=Type,
    #        value=`Percentage of students`,
    #        -year) %>%
  mutate(Estimate = case_when(grepl("_low", Type) ~ "Lower",
                          grepl("_upp", Type) ~ "Upper",
                          TRUE ~ "Mean"),
         User = case_when(grepl("ever", Type) ~ "Ever",
                          grepl("current", Type) ~ "Current",
                          TRUE ~ "Mean")) %>%
  dplyr::select(-Type) %>%
  pivot_wider(names_from = Estimate, 
              values_from = `Percentage of students`) %>%
  #spread(Estimate, `Percentage of students`) %>%
  ggplot(aes(x=year,y=Mean)) +
  geom_line(aes(linetype=User)) +
  geom_linerange(aes(ymin = Lower, ymax = Upper)) + 
  scale_linetype_manual(values = c(2,1)) +
    scale_y_continuous(breaks = seq(0,70,by=10),
                       labels = seq(0,70,by=10),
                       limits = c(0,70)) +
    theme_minimal() +
    theme(legend.position = "none",
          axis.title.x = element_blank()) +
    labs(title = "Nicotine product users becoming increasingly prevalent",
         y = "% of students")

plotB_w_8 <- nyts_data %>%
  filter((Grade == "8" & year == 2015) |
         (Grade == "9" & year == 2016) |
         (Grade == "10" & year == 2017) |
         (Grade == "11" & year == 2018) |
          (Grade == "12" & year == 2019) 
         ) %>%
    mutate(ecig_sum_ever = select(., EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           ecig_sum_current = select(., CELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               select(.,-EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               select(.,-CELCIGT) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(ecig_ever = case_when(ecig_sum_ever > 0 ~ TRUE,
                                    ecig_sum_ever ==0 ~ FALSE),
           ecig_current = case_when(ecig_sum_current > 0 ~ TRUE,
                                    ecig_sum_current ==0 ~ FALSE),
           non_ecig_ever = case_when(non_ecig_sum_ever > 0 ~ TRUE,
                                    non_ecig_sum_ever ==0 ~ FALSE),
           non_ecig_current = case_when(non_ecig_sum_current > 0 ~ TRUE,
                                    non_ecig_sum_current ==0 ~ FALSE)) %>%
  as_survey_design(strata = stratum, ids = psu, weight  = finwgt) %>%
    group_by(year) %>%
    summarise(ecig_ever_year = survey_mean(ecig_ever, vartype = "ci", na.rm=TRUE),
            ecig_current_year = survey_mean(ecig_current, vartype = "ci", na.rm=TRUE),
            non_ecig_ever_year = survey_mean(non_ecig_ever, vartype = "ci", na.rm=TRUE),
            non_ecig_current_year = survey_mean(non_ecig_current, vartype = "ci", na.rm=TRUE)) %>%
  mutate_at(vars(-year), "*", 100) %>%
  dplyr::select(year,
                ecig_ever_year,
                ecig_current_year,
                non_ecig_ever_year,
                non_ecig_current_year,
                contains("low"),
                contains("upp")) %>%
   pivot_longer(cols = -year, names_to = "Category", values_to = "Percentage of students")%>%
    # gather(key=Category,
    #        value=`Percentage of students`,
    #        -year)  %>%
  mutate(Estimate = case_when(grepl("_low", Category) ~ "Lower",
                          grepl("_upp", Category) ~ "Upper",
                          TRUE ~ "Mean"),
         User = case_when(grepl("current", Category) ~ "Current",
                          TRUE ~ "Ever",),
         Product = case_when(grepl("non_ecig", Category) ~ "Other products",
                          TRUE ~ "E-cigarettes")) %>%
  dplyr::select(-Category) %>%
  pivot_wider(names_from = Estimate, 
              values_from = `Percentage of students`) %>%
  #spread(Estimate, `Percentage of students`) %>%
  filter(User=="Ever") %>%
  dplyr::rename("Lower_temp" = Upper,
                "Upper_temp" = Lower) %>%
  dplyr::rename("Lower"=Lower_temp,
                "Upper"=Upper_temp) %>%
  ggplot(aes(x=year,y=Mean, color=Product)) +
  geom_line(linetype=1) +
  geom_linerange(aes(ymin = Lower, ymax = Upper)) + 
  scale_y_continuous(breaks = seq(10, 60, by = 10), limits = c(10,60)) +
    theme_minimal() +
    theme(legend.position = "none",
          axis.title.x = element_blank()) +
    labs(title = "% ever trying nicotine products increases",
         y = "% of students")

plotC_w_8 <- nyts_data %>%
  filter((Grade == "8" & year == 2015) |
         (Grade == "9" & year == 2016) |
         (Grade == "10" & year == 2017) |
         (Grade == "11" & year == 2018) |
          (Grade == "12" & year == 2019) 
         ) %>%
    mutate(ecig_sum_ever = select(., EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           ecig_sum_current = select(., CELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               select(.,-EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               select(.,-CELCIGT) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(ecig_ever = case_when(ecig_sum_ever > 0 ~ TRUE,
                                    ecig_sum_ever ==0 ~ FALSE),
           ecig_current = case_when(ecig_sum_current > 0 ~ TRUE,
                                    ecig_sum_current ==0 ~ FALSE),
           non_ecig_ever = case_when(non_ecig_sum_ever > 0 ~ TRUE,
                                    non_ecig_sum_ever ==0 ~ FALSE),
           non_ecig_current = case_when(non_ecig_sum_current > 0 ~ TRUE,
                                    non_ecig_sum_current ==0 ~ FALSE)) %>%
  as_survey_design(strata = stratum, ids = psu, weight  = finwgt) %>%
    group_by(year) %>%
  summarise(ecig_ever_year = survey_mean(ecig_ever, vartype = "ci", na.rm=TRUE),
            ecig_current_year = survey_mean(ecig_current, vartype = "ci", na.rm=TRUE),
            non_ecig_ever_year = survey_mean(non_ecig_ever, vartype = "ci", na.rm=TRUE),
            non_ecig_current_year = survey_mean(non_ecig_current, vartype = "ci", na.rm=TRUE)) %>%
  mutate_at(vars(-year), "*", 100) %>%
  dplyr::select(year,
                ecig_ever_year,
                ecig_current_year,
                non_ecig_ever_year,
                non_ecig_current_year,
                contains("low"),
                contains("upp")) %>%
  pivot_longer(cols = -year, names_to = "Category", values_to = "Percentage of students")%>%
    # gather(key=Category,
    #        value=`Percentage of students`,
    #        -year) %>%
    mutate(Estimate = case_when(grepl("_low", Category) ~ "Lower",
                          grepl("_upp", Category) ~ "Upper",
                          TRUE ~ "Mean"),
         User = case_when(grepl("ever", Category) ~ "Ever",
                          grepl("current", Category) ~ "Current"),
         Product = case_when(grepl("non_ecig", Category) ~ "Other products",
                          TRUE ~ "E-cigarettes")) %>%
  dplyr::select(-Category) %>%
  pivot_wider(names_from = Estimate, 
              values_from = `Percentage of students`) %>%
  #spread(Estimate, `Percentage of students`) %>%
    ggplot(aes(x=year,y=Mean, color=Product)) +
  geom_line(aes(linetype=User)) +
  geom_linerange(aes(ymin = Lower, ymax = Upper)) + 
  scale_linetype_manual(values = c(2,1)) +
  scale_y_continuous(breaks = seq(0, 60, by = 10), limits = c(0,60)) +
    theme_minimal() +
    theme(legend.position = "none",
          axis.title.x = element_blank()) +
    labs(title = "E-cigarette use surpasses use of other nicotine products",
         y = "% of students")

title_w_8 <- ggdraw() + 
  draw_label(
    expression("Among"~8^th~"graders in 2015, have vaping rates possibly influenced tobacco/nicotine use?"),
    fontface = 'bold',
    size=14,
    x = 0,
    hjust = 0
  ) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

plotsA_w_8 <- plot_grid(plotA_w_8,
                        rel_widths = c(1),
                        align = "v",
                        axis = "bt")

plotsBC_w_8 <- plot_grid(plotB_w_8,
                         plotC_w_8,
                         rel_widths = c(1,1),
                         axis = "bt")

legend_w_8 <- get_legend(plotB_w_8 +
                       theme(legend.position = "bottom",
                             legend.direction = "horizontal"))

figure_w_8 <- plot_grid(title_w_8,
                        plotsA_w_8,
                        plotsBC_w_8,
                        legend_w_8,
                        ncol = 1,
                        rel_heights = c(0.1,
                                      1,
                                      1,
                                      0.1),
                        scale = 1.0
)

figure_w_8

Final Figure

title_final <- ggdraw() +
  draw_label(
    expression("Have vaping rates possibly influenced tobacco/nicotine use?"),
    fontface = 'bold',
    size=16,
    x = 0.5) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

subtitle_uw_final <- ggdraw() + 
  draw_label(
    expression(~6^th~"-"~12^th~"graders, unweighted"),
    size=12,
    x = 0.5) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

subtitle_w_final <- ggdraw() + 
  draw_label(
    expression(~6^th~"-"~12^th~"graders, weighted"),
    fontface = 'bold',
    size=12,
    x = 0.5) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

subtitle_w_8_final <- ggdraw() + 
  draw_label(
    expression(~8^th~"graders in 2015, weighted"),
    fontface = 'bold',
    size=12,
    x = 0.5) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

subtitle_final <- plot_grid(subtitle_uw_final,
                            subtitle_w_final,
                            subtitle_w_8_final,
                            ncol = 3)

plotsA_title_final <- ggdraw() + 
  draw_label(
    expression("Prevalence of e-cigarette use by user type"),
    size=14,
    x = 0.5) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

plotsA_final <- plot_grid(plotA_uw + theme(plot.title = element_blank()),
                          plotA_w + theme(plot.title = element_blank()),
                          plotA_w_8 + theme(plot.title = element_blank()),
                          ncol = 3,
                          align = "v",
                          axis = "bt")

plotsB_title_final <- ggdraw() + 
  draw_label(
    expression("Prevalence of ever use by product type"),
    size=14,
    x = 0.5) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

plotsB_final <- plot_grid(plotB_uw + theme(plot.title = element_blank()),
                          plotB_w + theme(plot.title = element_blank()),
                          plotB_w_8 + theme(plot.title = element_blank()),
                          ncol = 3,
                          align = "v",
                          axis = "bt")

plotsC_title_final <- ggdraw() + 
  draw_label(
    expression("Prevalence of nicotine product use by product & user type"),
    size=14,
    x = 0.5) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

plotsC_final <- plot_grid(plotC_uw + theme(plot.title = element_blank()),
                          plotC_w + theme(plot.title = element_blank()),
                          plotC_w_8 + theme(plot.title = element_blank()),
                          ncol = 3,
                          align = "v",
                          axis = "bt")

legend_final <- get_legend(plotB_w +
                             theme(legend.position = "bottom",
                             legend.direction = "horizontal"))

final_plot <- plot_grid(title_final,
          plotsA_title_final,
          subtitle_final,
          plotsA_final,
          plotsB_title_final,
          subtitle_final,
          plotsB_final,
          plotsC_title_final,
          subtitle_final,
          plotsC_final,
          legend_final,
          ncol = 1,
          rel_heights = c(0.2,
                          0.2,
                          0.1,
                          1,
                          0.2,
                          0.1,
                          1,
                          0.2,
                          0.1,
                          1,
                          0.1))

final_plot

Suggested Homework


  • Apply survey weights to one of the figures produced in this case study in which weighted estimates were not produced. Include error bars in the updated figure.
    • Does the figure change after the application of survey weights?
    • If so, describe how.
  • Reproduce final_plot above for a different cohort of your choice.

Notes

Ever and current variables are limited to those shared by all years of data included in this case study.

New code: Knit time: 35.214 secs. Previous code: ~ 3 m.

Problems

I had difficulty producing a plot that succinctly presented a trend. It’s very easy to produce plots that are very useful once one is familiar with the data. Some plots, however, cannot stand alone and need additional context to be clear for those without prior knowledge of the data. When I first shared a plot I had been working on with others, it became clear that in my effort to present a complicated idea briefly I had left out information that would make the trend easily interpretable. To solve this issue, I began to present visualizations of the data alongside my original plot. The final figure I created contained several additional plots, each presenting the same trend at a different level than my initial plot.

My “centerpiece” plot is the middle plot in final_plot. The 8 plots around it help provide a very clear picture of what is going on in the US with regards to e-cigarette use and nicotine product use at large. On its own, it’s difficult to understand the trends in the US and how important the weighting scheme is for inference. Once you add the left and right columns, it’s clear what is going on.

Data Analysis


content header


Summary


Session info


R version 4.0.1 (2020-06-06)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Mojave 10.14.5

Matrix products: default
BLAS:   /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRblas.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] cowplot_1.0.0      ggplot2_3.3.1      srvyr_0.3.10       summarytools_0.9.6
 [5] readr_1.3.1        forcats_0.5.0      tidyr_1.1.0        stringr_1.4.0     
 [9] dplyr_1.0.0        purrr_0.3.4        readxl_1.3.1       knitr_1.28        
[13] here_0.1          

loaded via a namespace (and not attached):
 [1] tidyselect_1.1.0   xfun_0.14          pander_0.6.3       mitools_2.4       
 [5] splines_4.0.1      lattice_0.20-41    tcltk_4.0.1        colorspace_1.4-1  
 [9] vctrs_0.3.0        generics_0.0.2     htmltools_0.4.0    yaml_2.2.1        
[13] base64enc_0.1-3    utf8_1.1.4         survival_3.1-12    rlang_0.4.6       
[17] pillar_1.4.4       glue_1.4.1         withr_2.2.0        DBI_1.1.0         
[21] pryr_0.1.4         matrixStats_0.56.0 lifecycle_0.2.0    plyr_1.8.6        
[25] munsell_0.5.0      gtable_0.3.0       cellranger_1.1.0   codetools_0.2-16  
[29] evaluate_0.14      labeling_0.3       fansi_0.4.1        highr_0.8         
[33] Rcpp_1.0.4.6       backports_1.1.7    scales_1.1.1       checkmate_2.0.0   
[37] magick_2.3         farver_2.0.3       rapportools_1.0    hms_0.5.3         
[41] digest_0.6.25      stringi_1.4.6      survey_4.0         rprojroot_1.3-2   
[45] grid_4.0.1         cli_2.0.2          tools_4.0.1        magrittr_1.5      
[49] tibble_3.0.1       crayon_1.3.4       pkgconfig_2.0.3    ellipsis_0.3.1    
[53] Matrix_1.2-18      lubridate_1.7.8    assertthat_0.2.1   rmarkdown_2.2     
[57] R6_2.4.1           compiler_4.0.1    
LS0tCnRpdGxlOiAiT3BlbiBDYXNlIFN0dWRpZXMgOiBWYXBpbmcgQmVoYXZpb3JzIGluIEFtZXJpY2FuIFlvdXRoIgphdXRob3I6ICJNaWNoYWVsIE9udGl2ZXJvcywgQ2FycmllIFdyaWdodCwgUGhELiAiCgpjc3M6IHN0eWxlLmNzcwpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHNlbGZfY29udGFpbmVkOiB5ZXMKICAgIGNvZGVfZG93bmxvYWQ6IHllcwogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgbnVtYmVyX3NlY3Rpb25zOiBubwogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICBwZGZfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogIHdvcmRfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwoKLS0tCjxzdHlsZT4KI1RPQyB7CiAgYmFja2dyb3VuZDogdXJsKCJodHRwczovL29wZW5jYXNlc3R1ZGllcy5naXRodWIuaW8vaW1nL2xvZ28uanBnIik7CiAgYmFja2dyb3VuZC1zaXplOiBjb250YWluOwogIHBhZGRpbmctdG9wOiAyNDBweCAhaW1wb3J0YW50OwogIGJhY2tncm91bmQtcmVwZWF0OiBuby1yZXBlYXQ7Cn0KPC9zdHlsZT4KCmBgYHtyLCBlY2hvPUZBTFNFfQprbml0X3RpbWVfc3RhcnQgPC0gU3lzLnRpbWUoKQpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTgsIGRwaT0zMDApIApgYGAKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoaW5jbHVkZSA9IFRSVUUsIGNvbW1lbnQgPSBOQSwgZWNobyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgY2FjaGUgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIGZpZy5hbGlnbiA9ICJjZW50ZXIiLCBvdXQud2lkdGggPSAnOTAlJykKbGlicmFyeShoZXJlKQpsaWJyYXJ5KGtuaXRyKQpgYGAKCgojIyMjIHsub3V0bGluZSB9CmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aCA9ICI4MDAgcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAiZmluYWxfcGxvdC5wbmciKSkKYGBgCiMjIyMKCgoKCiMjIHsuZGlzY2xhaW1lcl9ibG9ja30KCioqRGlzY2xhaW1lcioqOiBUaGUgcHVycG9zZSBvZiB0aGUgW09wZW4gQ2FzZSBTdHVkaWVzXShodHRwczovL29wZW5jYXNlc3R1ZGllcy5naXRodWIuaW8pe3RhcmdldD0iX2JsYW5rIn0gcHJvamVjdCBpcyAqKnRvIGRlbW9uc3RyYXRlIHRoZSB1c2Ugb2YgdmFyaW91cyBkYXRhIHNjaWVuY2UgbWV0aG9kcywgdG9vbHMsIGFuZCBzb2Z0d2FyZSBpbiB0aGUgY29udGV4dCBvZiBtZXNzeSwgcmVhbC13b3JsZCBkYXRhKiouIEEgZ2l2ZW4gY2FzZSBzdHVkeSBkb2VzIG5vdCBjb3ZlciBhbGwgYXNwZWN0cyBvZiB0aGUgcmVzZWFyY2ggcHJvY2VzcywgaXMgbm90IGNsYWltaW5nIHRvIGJlIHRoZSBtb3N0IGFwcHJvcHJpYXRlIHdheSB0byBhbmFseXplIGEgZ2l2ZW4gZGF0YSBzZXQsIGFuZCBzaG91bGQgbm90IGJlIHVzZWQgaW4gdGhlIGNvbnRleHQgb2YgbWFraW5nIHBvbGljeSBkZWNpc2lvbnMgd2l0aG91dCBleHRlcm5hbCBjb25zdWx0YXRpb24gZnJvbSBzY2llbnRpZmljIGV4cGVydHMuIAoKIyMgKipNb3RpdmF0aW9uKioKKioqIApBY2NvcmRpbmcgdG8gYSByZWNlbnQgW3JlcG9ydF0oaHR0cHM6Ly93d3cuY2RjLmdvdi9tbXdyL3ZvbHVtZXMvNjgvd3IvbW02ODA2ZTEuaHRtP3NfY2lkPW1tNjgwNmUxX3cpe3RhcmdldD0iX2JsYW5rIn0sIG92ZXJhbGwgdG9iYWNjbyB1c2UgKippbmNyZWFzZWQqKiBpbiB5b3V0aHMgKG1pZGRsZSBzY2hvb2xhbmQgaGlnaCBzY2hvb2wgc3R1ZGVudHMpIGluIHRoZSBVbml0ZWQgU3RhdGVzIGluIDIwMTcgYW5kIDIwMTgsIGRlc3BpdGUgcHJldmlvdXMgeWVhcnMgb2YgZGVjbGluaW5nIHVzZS4KClRoaXMgbWFqb3IgaW5jcmVhc2UgaXMgYXR0cmlidXRlZCB0byBhbiBpbmNyZWFzZSBpbiB0aGUgdXNlIG9mIGVsZWN0cm9uaWMgY2lnYWFyZXR0ZSAoZS1jaWdhcmV0dGUpIHByb2R1Y3RzLgoKRS1jaWdhcmV0dGVzIGFyZSByZWZlcnJlZCB0byBieSBtYW55IGRpZmZlcmVudCBuYW1lcywgaW5jbHVkaW5nIGJ1dCBub3QgbGltaXRlZCB0bzoKCjEpIEVsZWN0cm9uaWMgbmljb3RpbmUgZGVsaXZlcnkgc3lzdGVtcyAoRU5EUykKMikgVmFwZXMKMykgZS1ob29rYWhzCjQpIHZhcGUgcGVucwo1KSB0YW5rcwo2KSBtb2RzCgpUaGUgZGV2aWNlcyB2YXJ5IGdyZWF0bHk6CgpgYGB7ciwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIifQoKaW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly93d3cubHVuZy5vcmcvZ2V0bWVkaWEvOGFjOGFiOGMtZTdmYy00OTdiLTgzODQtNDQxNjE1ZjUwZmYwL2VjaWdzX0suanBnLmpwZyIpCmBgYAoKIyMjIyMgW1tzb3VyY2VdKGh0dHBzOi8vd3d3Lmx1bmcub3JnL3F1aXQtc21va2luZy9lLWNpZ2FyZXR0ZXMtdmFwaW5nL2x1bmctaGVhbHRoKV0KClNlZSB0aGlzIFtDREMgZ3VpZGVdKGh0dHBzOi8vd3d3LmNkYy5nb3YvdG9iYWNjby9iYXNpY19pbmZvcm1hdGlvbi9lLWNpZ2FyZXR0ZXMvcGRmcy9lY2lnYXJldHRlLW9yLXZhcGluZy1wcm9kdWN0cy12aXN1YWwtZGljdGlvbmFyeS01MDgucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IGFuZCB0aGUgW0FtZXJpY2FuIEx1bmcgQXNzb2NpYXRpb24gd2Vic2l0ZV0oaHR0cHM6Ly93d3cubHVuZy5vcmcvcXVpdC1zbW9raW5nL2UtY2lnYXJldHRlcy12YXBpbmcvbHVuZy1oZWFsdGgpe3RhcmdldD0iX2JsYW5rIn0gZm9yIG1vcmUgaW5mb3JtYXRpb24uIAoKVGhlIHJlcG9ydCBmb3VuZCB0aGF0OgoKPiBEdXJpbmcgMjAxN+KAkzIwMTgsIGN1cnJlbnQgdXNlIG9mIGFueSB0b2JhY2NvIHByb2R1Y3QgKippbmNyZWFzZWQgMzguMyUqKiAoZnJvbSAxOS42JSB0byAyNy4xJSkgYW1vbmcgaGlnaCBzY2hvb2wgc3R1ZGVudHMgYW5kICoqMjguNiUqKiAoZnJvbSA1LjYlIHRvIDcuMiUpIGFtb25nIG1pZGRsZSBzY2hvb2wgc3R1ZGVudHM7IGUtY2lnYXJldHRlIHVzZSAqKmluY3JlYXNlZCA3Ny44JSoqIChmcm9tIDExLjclIHRvIDIwLjglKSBhbW9uZyBoaWdoIHNjaG9vbCBzdHVkZW50cyBhbmQgKio0OC41JSoqIChmcm9tIDMuMyUgdG8gNC45JSkgYW1vbmcgbWlkZGxlIHNjaG9vbCBzdHVkZW50cy4KCgpJbiAyMDE4LCB0aGUgW0ZlZGVyYWwgRHJ1ZyBBZG1pbmlzdHJhdGlvbiAoRkRBKSBpbiB0aGUgVW5pdGVkIFN0YXRlc10oaHR0cHM6Ly9hY3Nqb3VybmFscy5vbmxpbmVsaWJyYXJ5LndpbGV5LmNvbS9kb2kvZnVsbC8xMC4xMDAyL2NuY3IuMzE4Njgpe3RhcmdldD0iX2JsYW5rIn0gc3RhdGVkIHRoYXQgZS1jaWdhcmV0dGUgdXNhZ2UgdXNlIGFtb25nIHlvdXRoIHJlYWNoZWQ6ICAKCj4g4oCcbm90aGluZyBzaG9ydCBvZiBhbiAqKmVwaWRlbWljIHByb3BvcnRpb24gb2YgZ3Jvd3RoKirigJ0KCgpJbiB0aGlzIGNhc2Ugc3R1ZHksIHdlIHdpbGwgYmUgaW52aXN0aWdhdGluZyB0aGUgc2FtZSBkYXRhIHVzZWQgaW4gdGhlIHJlcG9ydCB0aGF0IGdlbmVyYXRlZCB0aGUgYWJvdmUgZmluZGluZ3MuIFRoaXMgZGF0YSBjb21lcyBmcm9tIHRoZSBbVGhlIE5hdGlvbmFsIFlvdXRoIFRvYmFjY28gU3VydmV5IChOWVRTKV0oaHR0cHM6Ly93d3cuY2RjLmdvdi90b2JhY2NvL2RhdGFfc3RhdGlzdGljcy9zdXJ2ZXlzL255dHMvaW5kZXguaHRtKXt0YXJnZXQ9Il9ibGFuayJ9LgoKIyMjIyB7LnJlZmVyZW5jZV9ibG9ja30KCkdlbnR6a2UsIEFuZHJlYSBTLiwgTWVsaXNhIENyZWFtZXIsIEthcmVuIEEuIEN1bGxlbiwgQnJpZGdldCBLLiBBbWJyb3NlLCBHb3Jkb24gV2lsbGlzLCBBaG1lZCBKYW1hbCwgYW5kIEJyaWFuIEEuIEtpbmcuICDigJxWaXRhbCBTaWduczogVG9iYWNjbyBQcm9kdWN0IFVzZSBBbW9uZyBNaWRkbGUgYW5kIEhpZ2ggU2Nob29sIFN0dWRlbnRzIC0gVW5pdGVkIFN0YXRlcywgMjAxMS0yMDE4LuKAnSAqKk1NV1IuIE1vcmJpZGl0eSBhbmQgTW9ydGFsaXR5IFdlZWtseSBSZXBvcnQqKiA2OCAoNik6IDE1N+KAkzY0ICgyMDE5KS4KCiMjIyMKCgojIyAqKk1haW4gUXVlc3Rpb25zKioKKioqIAoKIyMjIyB7Lm1haW5fcXVlc3Rpb25fYmxvY2t9CjxiPjx1PiBPdXIgbWFpbiBxdWVzdGlvbjogPC91PjwvYj4KCjEpIEhvdyBoYXMgdG9iYWNjby9uaWNvdGluZSB1c2UgYnkgQW1lcmljYW4geW91dGhzIGNoYW5nZWQgc2luY2UgMjAxNT8gCjIpIEhvdyBkbyB2YXBpbmcgcmF0ZXMgY29tcGFyZSBiZXR3ZWVuIG1hbGVzIGFuZCBmZW1hbGVzPwozKSBXaGF0IHZhcGluZyBicmFuZHMgYW5kIGZsYXZvcnMgYXBwZWFyIHRvIGJlIHVzZWQgdGhlIG1vc3QgZnJlcXVlbnRseT8gIApXZSB3aWxsIGJhc2UgdGhpcyBvbiB0aGUgZm9sbG93aW5nIHN1cnZleSBxdWVzdGlvbnM6ICAgCj4gIkR1cmluZyB0aGUgcGFzdCAzMCBkYXlzLCB3aGF0IGJyYW5kIG9mIGUtY2lnYXJldHRlcyBkaWQgeW91IHVzdWFsbHkgdXNlPyIgICAKPiJXaGF0IGZsYXZvcnMgb2YgdG9iYWNjbyBwcm9kdWN0cyBoYXZlIHlvdSB1c2VkIGluIHRoZSBwYXN0CjMwIGRheXM/IiAgCgo0KSBIYXZlIHZhcGluZyByYXRlcyBwb3NzaWJseSBpbmZsdWVuY2VkIHRvYmFjY28vbmljb3RpbmUgdXNlPwoKIyMjIwoKCiMjICoqTGVhcm5pbmcgT2JqZWN0aXZlcyoqIAoqKiogCgpJbiB0aGlzIGNhc2Ugc3R1ZHksIHdlIHdpbGwgY292ZXIgaG93IHRvIGltcG9ydCBkYXRhIGZyb20gbXVsdGlwbGUgZmlsZXMgZWZmaWNpZW50bHksIGhvdyB0byBpbXBvcnQgZGF0YSBmcm9tIGV4Y2VsIGZpbGVzLCBhbmQgaG93IHRvIG1ha2UgYSB2YXJpZXR5IG9mIHZpc3VhbGl6YXRpb25zIHRvIGNvbXBhcmUgbXVsdGlwbGUgZ3JvdXBzIGFjcm9zcyB0aW1lLiBXZSB3aWxsIGFsc28gZGVtb25zdHJhdGUgaG93IHRvIHdvcmsgd2l0aCBjb2RlYm9va3MuIFdlIHdpbGwgY292ZXIgdGhlIGNvbmNlcHQgb2Ygc3VydmV5IHdlaWdodGluZyBhbmQgaW50cm9kdWNlIHRoZSBgc3J2eXJgIHBhY2thZ2UuIFdlIHdpbGwgZGlzY3VzcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHBvb2xlZCBjcm9zcy1zZWN0aW9uYWwgZGF0YSBhbmQgcGFuZWwgZGF0YS4gV2Ugd2lsbCBlc3BlY2lhbGx5IGZvY3VzIG9uIHVzaW5nIHBhY2thZ2VzIGFuZCBmdW5jdGlvbnMgZnJvbSB0aGUgW2BUaWR5dmVyc2VgXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSBmb3Igd3JhbmdsaW5nIGRhdGEsIHN1Y2ggYXMgYHRpZHlyYCBhbmQgYGRweXJgIGFuZCBmb3IgdmlzdWFsaXphdGlvbiwgc3VjaCBhcyBhcyBgZ2dwbG90MmAuIFRoZSB0aWR5dmVyc2UgaXMgYSBsaWJyYXJ5IG9mIHBhY2thZ2VzIGNyZWF0ZWQgYnkgUlN0dWRpby4gV2hpbGUgc29tZSBzdHVkZW50cyBtYXkgYmUgZmFtaWxpYXIgd2l0aCBwcmV2aW91cyBSIHByb2dyYW1taW5nIHBhY2thZ2VzLCB0aGVzZSBwYWNrYWdlcyBtYWtlIGRhdGEgc2NpZW5jZSBpbiBSIGVzcGVjaWFsbHkgZWZmaWNpZW50LgoKCmBgYHtyLCBvdXQud2lkdGggPSAiMjAlIiwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIifQoKaW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly90aWR5dmVyc2UudGlkeXZlcnNlLm9yZy9sb2dvLnBuZyIpCmBgYAoKCioqKiAKCgpXZSB3aWxsIGJlZ2luIGJ5IGxvYWRpbmcgdGhlIHBhY2thZ2VzIHRoYXQgd2Ugd2lsbCBuZWVkOgoKYGBge3J9CmxpYnJhcnkoaGVyZSkKbGlicmFyeShyZWFkeGwpCmxpYnJhcnkocHVycnIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeSh0aWR5cikKbGlicmFyeShmb3JjYXRzKQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KHN1bW1hcnl0b29scykKbGlicmFyeShzcnZ5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGNvd3Bsb3QpCmBgYAoKIFBhY2thZ2UgICB8IFVzZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKLS0tLS0tLS0tLSB8LS0tLS0tLS0tLS0tLQpbaGVyZV0oaHR0cHM6Ly9naXRodWIuY29tL2plbm55YmMvaGVyZV9oZXJlKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgIHwgdG8gZWFzaWx5IGxvYWQgYW5kIHNhdmUgZGF0YSAgCltyZWFkeGxdKGh0dHBzOi8vcmVhZHhsLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBpbXBvcnQgdGhlIGRhdGEgaW4gdGhlIGV4Y2VsIGZpbGVzICAKW3B1cnJyXShodHRwczovL3B1cnJyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgfCB0byBpbXBvcnQgdGhlIGRhdGEgaW4gYWxsIHRoZSBkaWZmZXJlbnQgZXhjZWwgYW5kIGNzdiBmaWxlcyBlZmZpY2llbnRseQpbcmVhZHJdKGh0dHBzOi8vcmVhZHIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGltcG9ydCB0aGUgQ1NWIGZpbGUgZGF0YQpbZHBseXJdKGh0dHBzOi8vZHBseXIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGFycmFuZ2UvZmlsdGVyL3NlbGVjdC9jb21wYXJlIHNwZWNpZmljIHN1YnNldHMgb2YgdGhlIGRhdGEgIApbc3VtbWFyeXRvb2xzXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvc2tpbXIvaW5kZXguaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gZ2V0IGFuIG92ZXJ2aWV3IG9mIGRhdGEgaW4gYSBkaWZmZXJlbnQgc3R5bGUgICAKW3RpZHlyXShodHRwczovL3RpZHlyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byByZWFycmFuZ2UgZGF0YSBpbiB3aWRlIGFuZCBsb25nIGZvcm1hdHMgCgoKW3N0cmluZ3JdKGh0dHBzOi8vc3RyaW5nci50aWR5dmVyc2Uub3JnL2FydGljbGVzL3N0cmluZ3IuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgICB8IHRvIG1hbmlwdWxhdGUgdGhlIGNoYXJhY3RlciBzdHJpbmdzIHdpdGhpbiB0aGUgZGF0YSAgIApbZ2dwbG90Ml0oaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgIHwgdG8gbWFrZSB2aXN1YWxpemF0aW9ucyB3aXRoIG11bHRpcGxlIGxheWVycyAgCltnZ3B1YnJdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9nZ3B1YnIvaW5kZXguaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgICB8IHRvIGVhc2lseSBhZGQgcmVncmVzc2lvbiBsaW5lIGVxdWF0aW9ucyB0byBwbG90cyAgCltmb3JjYXRzXShodHRwczovL2ZvcmNhdHMudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgfCB0byBjaGFuZ2UgZGV0YWlscyBhYm91dCBmYWN0b3JzIChjYXRlZ29yaWNhbCB2YXJpYWJsZXMpICAKW2xtZXJUZXN0XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvbG1lclRlc3QvbG1lclRlc3QucGRmKXwgdG8gcGVyZm9ybSBsaW5lYXIgbWl4ZWQgbW9kZWwgdGVzdGluZyAgIApbY2FyXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvY2FyL2Nhci5wZGYpfCB0byBwZXJmb3JtIExldmVuZSdzIFRlc3Qgb2YgSG9tb2dlbmVpdHkgb2YgVmFyaWFuY2VzICAgCltnZ2lyYXBoXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvZ2dpcmFwaC9pbmRleC5odG1sKXwgdG8gbWFrZSBwbG90cyBpbnRlcmFjdGl2ZSAgIApbZ2dmb3JjZV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2dnZm9yY2UvZ2dmb3JjZS5wZGYpfCB0byBtb2RpZnkgZmFjZXRzIGluIHBsb3RzICAKW3ZpcmlkaXNdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy92aXJpZGlzL3ZpZ25ldHRlcy9pbnRyby10by12aXJpZGlzLmh0bWwpfCB0byBwbG90IGluIGNvbG9yIHBhbGV0dGUgICAgCltjb3dwbG90XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvY293cGxvdC92aWduZXR0ZXMvaW50cm9kdWN0aW9uLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBhbGxvdyBwbG90cyB0byBiZSBjb21iaW5lZCAgIFtza2ltcl0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3NraW1yL2luZGV4Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGdldCBhbiBvdmVydmlldyBvZiBkYXRhICAgCgoKCgpUaGUgZmlyc3QgdGltZSB3ZSB1c2UgYSBmdW5jdGlvbiwgd2Ugd2lsbCB1c2UgdGhlIGA6OmAgdG8gaW5kaWNhdGUgd2hpY2ggcGFja2FnZSB3ZSBhcmUgdXNpbmcuIFVubGVzcyB3ZSBoYXZlIG92ZXJsYXBwaW5nIGZ1bmN0aW9uIG5hbWVzLCB0aGlzIGlzIG5vdCBuZWNlc3NhcnksIGJ1dCB3ZSB3aWxsIGluY2x1ZGUgaXQgaGVyZSB0byBiZSBpbmZvcm1hdGl2ZSBhYm91dCB3aGVyZSB0aGUgZnVuY3Rpb25zIHdlIHdpbGwgdXNlIGNvbWUgZnJvbS4KCgojIyAqKkNvbnRleHQqKgoqKiogCgpBY2NvcmRpbmcgdG8gdGhlIGNpdGVkIFtNb3JiaWRpdHkgYW5kIE1vcnRhbGl0eSBXZWVrbHkgUmVwb3J0XShodHRwczovL3d3dy5jZGMuZ292L21td3Ivdm9sdW1lcy82OC93ci9tbTY4MDZlMS5odG0/c19jaWQ9bW02ODA2ZTFfdykgdGhpcyB3YXMgd2hhdCB3YXMgYWxyZWFkeSBrbm93biBhYm91dCB0aGlzIHRvcGljIGFuZCB0aGUgaW1wbGljYXRpb25zIG9mIHRoaXMgc3R1ZHk6CgpgYGB7ciwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIiLCBvdXQud2lkdGggPSAiODAwIHB4In0KCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJjb250ZXh0LnBuZyIpKQoKYGBgCgoKSW1wb3J0YW50bHksIHRoZSB2YXBvcnMgdXNlZCBpbiBlLWNpZ2FyZXR0ZXMgY29udGFpbiBoYXJtZnVsIGNoZW1pY2FsczoKCmBgYHtyLCBlY2hvID0gRkFMU0UsIGZpZy5hbGlnbiA9ImNlbnRlciJ9CgppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL3d3dy5jZGMuZ292L3RvYmFjY28vYmFzaWNfaW5mb3JtYXRpb24vZS1jaWdhcmV0dGVzL2ltYWdlcy9lLWNpZ2FyZXR0ZS1hZXJvc29sLWNhbi1jb250YWluLWhhcm1mdWwtaW5ncmVkaWVudHMtZGVza3RvcC03MDAuanBnIikKYGBgCgpFLWNpZ2FyZXR0ZSB1c2FnZSBoYXMgYWxzbyBiZWVuIGFzc29jaWF0ZWQgd2l0aCBbbHVuZyBpbmp1cnldKChodHRwczovL3d3dy5mcm9udGllcnNpbi5vcmcvYXJ0aWNsZXMvMTAuMzM4OS9mcGhhci4yMDE5LjAxNjE5L2Z1bGwpKXt0YXJnZXQ9Il9ibGFuayJ9CgpgYGB7ciwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIiLCBvdXQud2lkdGggPSAiODAwIHB4In0KCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJsdW5nLnBuZyIpKQpgYGAKClNlZSBbaGVyZV0oaHR0cHM6Ly93d3cuY2RjLmdvdi90b2JhY2NvL2Jhc2ljX2luZm9ybWF0aW9uL2UtY2lnYXJldHRlcy9RdWljay1GYWN0cy1vbi10aGUtUmlza3Mtb2YtRS1jaWdhcmV0dGVzLWZvci1LaWRzLVRlZW5zLWFuZC1Zb3VuZy1BZHVsdHMuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSBmb3IgYWRkaXRvbmFsIGluZm9ybWF0aW9uIGFib3V0IHRoZSBwb3RlbnRpYWwgaGVhbHRoIGVmZmVjdHMgb2YgZS1jaWdhcmV0dGVzIGluIHRlZW5zIGFuZCB5b3VuZyBhZHVsdHMuCgojIyAqKkxpbWl0YXRpb25zKioKKioqIApUaGVyZSBhcmUgc29tZSBpbXBvcnRhbnQgY29uc2lkZXJhdGlvbnMgcmVnYXJkaW5nIHRoaXMgZGF0YSBhbmFseXNpcyB0byBrZWVwIGluIG1pbmQ6IAoKMSkgVGhlIGRhdGEgaW5jbHVkZWQgaW4gdGhlIFtOYXRpb25hbCBZb3V0aCBUb2JhY2NvIFN1cnZleSAoTllUUyldKGh0dHBzOi8vd3d3LmNkYy5nb3YvdG9iYWNjby9kYXRhX3N0YXRpc3RpY3Mvc3VydmV5cy9ueXRzL2luZGV4Lmh0bSl7dGFyZ2V0PSJfYmxhbmsifSBkb2VzIG5vdCBmb2xsb3cgdGhlIHNhbWUgaW5kaXZpZHVhbCBzdHVkZW50cyBvdmVyIHRpbWUuICBBIFtsb25naXR1ZGluYWwgc3R1ZHldKGh0dHBzOi8vd3d3LmJtai5jb20vYWJvdXQtYm1qL3Jlc291cmNlcy1yZWFkZXJzL3B1YmxpY2F0aW9ucy9lcGlkZW1pb2xvZ3ktdW5pbml0aWF0ZWQvNy1sb25naXR1ZGluYWwtc3R1ZGllcyl7dGFyZ2V0PSJfYmxhbmsifSB0aGF0IGRvZXMgZm9sbG93IHRoZSBzYW1lIGluZGl2aWR1YWxzIG92ZXIgdGltZSBjb2xsZWN0cyBkYXRhIGNhbGxlZCBbcGFuZWwgZGF0YV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvUGFuZWxfZGF0YSkuIFRoZSBkYXRhIGluIHRoaXMgc3R1ZHkgaXMgY2FsbGVkIHBvb2xlZCBbY3Jvc3Mtc2VjdGlvbmFsIGRhdGFdaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ3Jvc3Mtc2VjdGlvbmFsX2RhdGEsIHRoaXMgZGF0YSBpcyBvYnRhaW5lZCBmcm9tIHJhbmRvbSBjb2xsZWN0aW9uIG9mIG9iZXJ2YXRpb25zIGFjcm9zcyB0aW1lLgoKQWNjb3JkaW5nIHRvIHdpa2lwZWRpYToKPlBhbmVsIGRhdGEgZGlmZmVycyBmcm9tIHBvb2xlZCBjcm9zcy1zZWN0aW9uYWwgZGF0YSBhY3Jvc3MgdGltZSwgYmVjYXVzZSBpdCBkZWFscyB3aXRoIHRoZSBvYnNlcnZhdGlvbnMgb24gdGhlIHNhbWUgc3ViamVjdHMgaW4gZGlmZmVyZW50IHRpbWVzIHdoZXJlYXMgdGhlIGxhdHRlciBvYnNlcnZlcyBkaWZmZXJlbnQgc3ViamVjdHMgaW4gZGlmZmVyZW50IHRpbWUgcGVyaW9kcwoKMikgVGhlIGRhdGEgYWxzbyBpbmNsdWRlcyBwZXJjZW50YWdlcyBvZiBzdHVkZW50cyB0aGF0IHJlcG9ydGVkIHVzZSBvZiBwYXJ0aWN1bGFyIHRvYmFjY28gcHJvZHVjdCwgYnV0IHRoZSBzdXJ2ZXkgcXVlc3Rpb25zIGRpZCBub3QgYXNrIGhvdyBtdWNoIHVzZXMgb2Ygb25lIHByb2R1Y3QgY29tcGFyZWQgdG8gYW5vdGhlciAtIGZvciBleGFtcGxlIHRoZSBzdXJ2ZXkgYXNrZWQgcXVlc3Rpb25zIGxpa2U6IldoYXQgZmxhdm9ycyBvZiB0b2JhY2NvIHByb2R1Y3RzIGhhdmUgeW91IHVzZWQgaW4gdGhlIHBhc3QgMzAgZGF5cz8iIFRodXMsIGl0IGlzIHVuY2xlYXIgaG93IG9mdGVuIG9uZSBmbGF2b3Igd2FzIHVzZWQgYnkgdGhlIHNhbWUgaW5kaXZpZHVhbCBvdmVyIGFub3RoZXIuCgpXaGlsZSBbZ2VuZGVyXShodHRwczovL3d3dy5nZW5kZXJzcGVjdHJ1bS5vcmcvcXVpY2stbGlua3MvdW5kZXJzdGFuZGluZy1nZW5kZXIvKXt0YXJnZXQ9Il9ibGFuayJ9IGFuZCBbc2V4XShodHRwczovL3d3dy53aG8uaW50L2dlbm9taWNzL2dlbmRlci9lbi9pbmRleDEuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSBhcmUgbm90IGFjdHVhbGx5IGJpbmFyeSwgdGhlIGRhdGF1c2VkIGluIHRoaXMgYW5hbHlzaXMgb25seSBjb250YWlucyBpbmZvcm1hdGlvbiBmb3IgZ3JvdXBzIG9mIGluZGl2aWR1YWxzIHdobyBhbnN3ZXJlZCB0aGUgc3VydmV5IHF1ZXN0aW9ucyBhcyBtYWxlIG9yIGZlbWFsZS4gCgojIyAqKldoYXQgYXJlIHRoZSBkYXRhPyoqCioqKiAKIApUaGUgZGF0YSBpbiB0aGlzIGNhc2Ugc3R1ZHkgY29tZXMgZnJvbSB0aGUgW05hdGlvbmFsIFlvdXRoIFRvYmFjY28gU3VydmV5IChOWVRTKV0oaHR0cHM6Ly93d3cuY2RjLmdvdi90b2JhY2NvL2RhdGFfc3RhdGlzdGljcy9zdXJ2ZXlzL255dHMvaW5kZXguaHRtKXt0YXJnZXQ9Il9ibGFuayJ9IHdoaWNoIGlzIGFuIGFubnVhbCBzdXJ2ZXkgdGhhdCBhc2tzIHN0dWRlbnRzICBpbiBoaWdoIHNjaG9vbCBhbmQgbWlkZGxlIHNjaG9vbCAoZ3JhZGVzIDYtMTIpIGFib3V0IHRvYmFjY28gdXNhZ2UgaW4gdGhlIFVuaXRlZCBTdGF0ZXMgb2YgQW1lcmljYS4KClRoZSBkYXRhIGZvciB0aGlzIHN1cnZleSBpcyBmcmVlbHkgYXZhaWxhYmxlIG9ubGluZSBhdCB0aGlzIFt3ZWJzaXRlXShodHRwczovL3d3dy5jZGMuZ292L3RvYmFjY28vZGF0YV9zdGF0aXN0aWNzL3N1cnZleXMvbnl0cy9kYXRhL2luZGV4Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gd2l0aCBkYXRhIGZyb20gMTk5OSwgMjAwMCwgMjAwMiwgMjAwNCwgMjAwNiwgMjAwOSwgIGFuZCAyMDExLTIwMTkuIFdlIHdpbGwgYmUgdXNpbmcgZGF0YSBmcm9tICoqMjAxNS0yMDE5KiogZHVlIHRvIHRoZSBmYWN0IHRoYXQgdGhlc2UgeWVhcnMgYXJlIHRoZSBtb3N0IHJlY2VudCB0aGF0IGFza2VkIHF1ZXN0aW9ucyByZWNhcmRpbmcgZS1jaWdhcmV0dGUgdXNhZ2UuCgpFYWNoIHllYXIgaW5jbHVkZXMgZG9jdW1lbnRhdGlvbiwgc3VjaCBhcyBhIFtjb2RlYm9va10oaHR0cHM6Ly93d3cuaWNwc3IudW1pY2guZWR1L2ljcHNyd2ViL2NvbnRlbnQvc2hhcmVkL0lDUFNSL2ZhcXMvd2hhdC1pcy1hLWNvZGVib29rLmh0bWwpIGFuZCBhbiBleGNlbCBmaWxlIGNvbnRhaW5pbmcgdGhlIGRhdGE6CgpgYGB7ciwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIiLCBvdXQud2lkdGggPSAiNjAwIHB4In0KCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJkYXRhLnBuZyIpKQpgYGAKVGhlcmVmb3JlLCBzaW5jZSB3ZSBhcmUgdXNpbmcgZGF0YSBmcm9tICoqMjAxNS0yMDE5KiosIHRoZSBkYXRhIHdlIGFyZSBpbnRlcmVzdGVkIGluIGlzIGxvY2F0ZWQgaW4gNSBkaWZmZXJlbnQgZXhjZWwgZmlsZXMsIGVhY2ggd2l0aCB0aGVpciBvd24gW2NvZGVib29rXShodHRwczovL3d3dy5pY3Bzci51bWljaC5lZHUvaWNwc3J3ZWIvY29udGVudC9zaGFyZWQvSUNQU1IvZmFxcy93aGF0LWlzLWEtY29kZWJvb2suaHRtbCkuCgpUaGUgW2NvZGVib29rXShodHRwczovL3d3dy5pY3Bzci51bWljaC5lZHUvaWNwc3J3ZWIvY29udGVudC9zaGFyZWQvSUNQU1IvZmFxcy93aGF0LWlzLWEtY29kZWJvb2suaHRtbCkgY29udGFpbnMgaW5mb3JtYXRpb24gZGVzY3JpYmluZyB0aGUgZGF0YSB3aXRoaW4gdGhlIGV4Y2VsIGZpbGUuIAoKQXMgeW91IGNhbiBzZWUgdGhlIGV4Y2VsIGZpbGUgY29udGFpbnMgdmVyeSBzaG9ydCB2YXJpYWJsZSBuYW1lcyBhbmQgdmFsdWVzLCBhbmQgaXQgaXMgbm90IGNsZWFyIHdoYXQgdGhleSBtZWFuIHdpdGhvdXQgdGhlIGNvZGVib29rOgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIiwgb3V0LndpZHRoID0gIjYwMCBweCJ9Cgprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAiZXhjZWwucG5nIikpCmBgYAoKVGhlIGNvZGVib29rIGV4cGxhaW5zIHdoYXQgdGhlIHZhcmlhYmxlcyAodGhlIGNvbHVtbnMpIGFyZToKYGBge3IsIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIiwgb3V0LndpZHRoID0gIjYwMCBweCJ9Cgprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAidmFyaWFibGVzLnBuZyIpKQpgYGAKCkFuZCB0aGUgY29kZWJvb2sgZXhwbGFpbnMgd2hhdCB0aGUgdmFsdWVzIGZvciBlYWNoIHZhcmlhYmxlIGFyZToKCmBgYHtyLCBlY2hvID0gRkFMU0UsIGZpZy5hbGlnbiA9ImNlbnRlciIsIG91dC53aWR0aCA9ICI2MDAgcHgifQoKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgInFuMS5wbmciKSkKYGBgCgpXZSB3aWxsIGV4cGxhaW4gbW9yZSBsYXRlciBhYm91dCB3aGF0IHRoZSB2YWx1ZXMgb24gdGhlIHJpZ2h0IGluZGljYXRlLgoKVGhlIHJlYXNvbiB0aGF0IHRoZXJlIGFyZSBjb2RlYm9va3MgZm9yIGVhY2ggeWVhciBpcyBiZWNhdXNlIHRoZSBxdWVzdGlvbnMgYXNrZWQgeWVhciB2YXJpZWQgc2xpZ2h0bHkuCgoKVGhlIGRhdGEgaW4gdGhpcyBzdXJ2ZXkgaXMgd2hhdCBpcyBjYWxsZWQgcG9vbGVkIGNyb3NzLXNlY3Rpb25hbCBkYXRhLiBJbiBvdGhlcndvcmRzLCBkaWZmZXJlbnQgc3Vic2V0cyBvZiBzdHVkZW50cyBhcmUgc3VydmV5ZWQgZWFjaCB5ZWFyIGFuZCBpdCBpcyBub3QgY2xlYXIgd2hpY2gsIGlmIGFueSAsIGluZGl2aWR1YWxzIHBhcnRpY3BhdGUgZnJvbSBvbmUgeWVhciB0byB0aGUgbmV4dC4KCiMjICoqRGF0YSBJbXBvcnQqKgoqKiogCgojIyMgUmVhZGluZyBpbiB0aGUgZXhjZWwgZmlsZXMKKioqClNpbmNlIHRoZXNlIGV4Y2VsIGZpbGVzIGFyZSBzbyBsYXJnZSAoZWFjaCBoYXMgcm91Z2hseSAyMCwwMDAgcm93cyksIGl0IHRha2VzIGEgYml0IG9mIHRpbWUgZm9yIHRoZSBkYXRhIHRvIGxvYWQuIFRvIG1ha2UgdGhlIHByb2Nlc3MgZmFzdGVyLCB3ZSBwcmV2aW91c2x5IGltcG9ydGVkIHRoZXNlIGZpbGVzLCBzZWxlY3RlZCBvbmx5IG91ciBxdWVzdGlvbnMgb2YgaW50ZXJlc3QsIGFuZCBzYXZlZCB0aGlzIGRhdGEgYXMgY3N2IGZpbGVzLiAKCjxkZXRhaWxzPjxzdW1tYXJ5PiBDbGljayBoZXJlIGZvciBkZXRhaWxzIG9uIGhvdyB0aGUgZGF0YSB3YXMgb3JpZ2luYWxseSBpbXBvcnRlZCA8L3N1bW1hcnk+CgpGaXJzdCB3ZSBjcmVhdGVkIGEgbGlzdCBvZiBmaWxlbmFtZXMgb2YgYWxsIHRoZSBkaWZmZXJlbnQgZXhjZWwgZmlsZXMuIFVzaW5nIHRoZSBgaGVyZSgpYCBmdW5jdGlvbiBvZiB0aGUgYGhlcmVgIHBhY2thZ2UsIHdlIGxvb2tlZCBpbiBhbGwgdGhlIGRpcmVjdG9yaWVzIG9mIHRoZSBwcm9qZWN0LgpUaGUgYGxpc3QuZmlsZXMoKWAgZnVuY3Rpb24gbG9va2VkIGZvciBhbGwgZmlsZXMgd2l0aCAueGxzeCB3aXRoaW4gdGhlc2Ugc3ViZGlyZWN0b3JpZXMuCmBgYHtyfQpleGNlbF9maWxlczwtbGlzdC5maWxlcyhoZXJlOjpoZXJlKCksIHJlY3Vyc2l2ZSA9IFRSVUUsCiAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiKi54bHN4IikKZXhjZWxfZmlsZXMKYGBgCgpBbGwgdGhlIGZpbGVzIHdlcmUgcmVhZCB1c2luZyBgcmVhZF9leGNlbCgpYCBvZiB0aGUgYHJlYWR4bGAgcGFja2FnZS4gVXNpbmcgdGhlIGBtYXAoKWAgZnVuY3Rpb24gb2YgdGhlIGBwdXJycmAgcGFja2FnZSB0aGlzIHdhcyBkb25lIGVmZmljaWVudGx5IGZvciBhbGwgb2YgdGhlIGV4Y2VsIGZpbGVzIGluIHRoZSBsaXN0IHVzaW5nIG9uZSBjb21tYW5kLiBUaGUgYC5gIGlzIHVzZWQgdG8gaW5kaWNhdGUgdGhhdCB3ZSB3YW50IHRvIGFwcGx5IHRoZSBgcmVhZF9leGNlbCgpYCBmdW5jdGlvbiB0byB0aGUgZGF0YSB0aGF0IHdlIGp1c3QgcGlwZWQgaW50byB0aGUgYG1hcCgpYCBmdW5jdGlvbi4KCkhlcmUgd2lsbCBhbHNvIHVzZWQgdGhlIGAlPiVgIHBpcGUgd2hpY2ggY2FuIGJlIHVzZWQgdG8gZGVmaW5lIHRoZSBpbnB1dCBmb3IgbGF0ZXIgc2VxdWVudGlhbCBzdGVwcy4gCgpUaGlzIGNyZWF0ZWQgYSBzaW5nbGUgbGlzdCBvZiB0aWJibGVzIChvbmUgZm9yIGVhY2ggZmlsZSkuIApgYGB7ciwgZXZhbCA9IEZBTFNFfQp0YmxfZmlsZXMgPC0gZXhjZWxfZmlsZXMgJT4lIAogICAgICAgbWFwKH5yZWFkeGw6OnJlYWRfZXhjZWwoLikpCmBgYAoKRWFjaCBleGNlbCBmaWxlIG5hbWUgd2FzIGV4dHJhY3RlZCB1c2luZyB0aGUgYHN0cl9leHRyYWN0KClgIGZ1bmN0aW9uIG9mIHRoZSBgc3RyaW5ncmAgcGFja2FnZS4gSGVyZSB3ZSBhcmUga2VlcGluZyBvY2N1cmFuY2VzIG9mIHRoZSBjaGFyYWN0ZXIgc3RyaW5nICJueXRzMjAxIiBmb2xsb3dlZCBieSBhICI1IiwiNiIsIjciLCI4Iiwgb3IgIjkiLgpgYGB7cn0KdGJsX25hbWVzIDwtIGV4Y2VsX2ZpbGVzICU+JQogIHN0cl9leHRyYWN0KCJueXRzWzJdWzBdWzFdWzUtOV0iKQoKdGJsX25hbWVzCmBgYAoKVGhlc2UgbmFtZXMgYmVjYW1lIHRoZSBuYW1lcyBvZiB0aGUgdGliYmxlcyBpbiB0aGUgbGlzdCBvZiB0aWJibGVzLgpgYGB7ciwgZXZhbCA9IEZBTFNFfQpuYW1lcyh0YmxfZmlsZXMpIDwtIHRibF9uYW1lcwpgYGAKCgpTcGVjaWZpYyBjb2x1bW5zIHdlcmUgc2VsZWN0ZWQgZnJvbSBlYWNoIG9mIHRoZSB0aWJibGVzIHVzaW5nIHRoZSB2YXJhaWJsZSBuYW1lLCBhcyBpZGVudGlmaWVkIGluIHRoZSBjb2RlYm9vayBmb3IgYmVpbmcgb2YgaW50ZXJlc3QuCkluIHNvbWUgY2FzZXMgZnVuY3Rpb25zIGxpa2UgYHN0YXJ0c193aXRoKClgIG9mIHRoZSBgZHBseXJgIHBhY2thZ2Ugd2VyZSB1c2VkIHRvIHNlbGVjdCBzZXZlcmFsIHZhcmlhYmxlcy4gTW9zdCBvZiB0aGUgc3VydmV5IHF1ZXN0aW9ucyBhYm91dCB0b2JhY2NvIHVzZSBzdGFydCB3aXRoIGFuIGAiRSJgIG9yIGEgYCJDImAgYWNjb3JkaW5nIHRvIHRoZSBjb2RlYm9va3MuIAoKYGBge3IsIGV2YWwgPSBGQUxTRX0KCnRibF9maWxlc1tbIm55dHMyMDE1Il1dIDwtIHRibF9maWxlc1tbIm55dHMyMDE1Il1dICU+JQogICAgZHBseXI6OnNlbGVjdChwc3UsICNQcmltYXJ5IFNhbXBsaW5nIFVuaXQKICAgICAgICAgICAgICAgICAgZmlud2d0LCNBbmFseXNpcyBXZWlnaHQKICAgICAgICAgICAgICAgICAgc3RyYXR1bSwjU2FtcGxpbmcgc3RyYXR1bQogICAgICAgICAgICAgICAgICBRbjEsICNBZ2UKICAgICAgICAgICAgICAgICAgUW4yLCAjU2V4CiAgICAgICAgICAgICAgICAgIFFuMywgI0dyYWRlCiAgICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJFIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JlLmNhc2UgPSBGQUxTRSksCiAgICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJDIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JlLmNhc2UgPSBGQUxTRSksCiAgICAgICAgICAgICAgICAgICkKCgp0YmxfZmlsZXNbWyJueXRzMjAxNiJdXSA8LSB0YmxfZmlsZXNbWyJueXRzMjAxNiJdXSAlPiUKICAgIGRwbHlyOjpzZWxlY3QocHN1LAogICAgICAgICAgICAgICAgICBmaW53Z3QsCiAgICAgICAgICAgICAgICAgIHN0cmF0dW0sCiAgICAgICAgICAgICAgICAgIFExLCAjQWdlCiAgICAgICAgICAgICAgICAgIFEyLCAjU2V4CiAgICAgICAgICAgICAgICAgIFEzLCAjR3JhZGUKICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIkUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZ25vcmUuY2FzZSA9IEZBTFNFKSwKICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIkMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZ25vcmUuY2FzZSA9IEZBTFNFKSwKICAgICAgICAgICAgICAgICAgUTUwQSwgI01lbnRob2wgIyBXaGF0IGZsYXZvcnMgb2YgdG9iYWNjbyBwcm9kdWN0cyBoYXZlIHlvdSB1c2VkIGluIHRoZSBwYXN0IDMwIGRheXM/IChTZWxlY3Qgb25lIG9yIG1vcmUpCiAgICAgICAgICAgICAgICAgIFE1MEIsICNDbG92ZSBvciBzcGljZQogICAgICAgICAgICAgICAgICBRNTBDLCAjRnJ1aXQKICAgICAgICAgICAgICAgICAgUTUwRCwgI0Nob2NvbGF0ZQogICAgICAgICAgICAgICAgICBRNTBFLCAjQWxjb2hvbGljIERyaW5rCiAgICAgICAgICAgICAgICAgIFE1MEYsICNDYW5keS9EZXNzZXJ0cy9PdGhlciBTd2VldHMKICAgICAgICAgICAgICAgICAgUTUwRywgI1NvbWUgT3RoZXIgRmxhdm9yIE5vdCBMaXN0ZWQgSGVyZQogICAgICAgICAgICAgICAgICBRNTBIICNJIERpZCBOb3QgVXNlIEZsYXZvcmVkIFRvYmFjY28gUHJvZHVjdHMgSW4gdGhlIFBhc3QKICAgICAgICAgICAgICAgICAgKSAKCnRibF9maWxlc1tbIm55dHMyMDE3Il1dIDwtIHRibF9maWxlc1tbIm55dHMyMDE3Il1dICU+JQogICAgZHBseXI6OnNlbGVjdChwc3UsCiAgICAgICAgICAgICAgICAgIGZpbndndCwKICAgICAgICAgICAgICAgICAgc3RyYXR1bSwKICAgICAgICAgICAgICAgICAgUTEsICNBZ2UKICAgICAgICAgICAgICAgICAgUTIsICNTZXgKICAgICAgICAgICAgICAgICAgUTMsICNHcmFkZQogICAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiRSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlnbm9yZS5jYXNlID0gRkFMU0UpLAogICAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiQyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlnbm9yZS5jYXNlID0gRkFMU0UpLAogICAgICAgICAgICAgICAgICBRNTBBLCAjTWVudGhvbCAjIFdoYXQgZmxhdm9ycyBvZiB0b2JhY2NvIHByb2R1Y3RzIGhhdmUgeW91IHVzZWQgaW4gdGhlIHBhc3QgMzAgZGF5cz8gKFNlbGVjdCBvbmUgb3IgbW9yZSkKICAgICAgICAgICAgICAgICAgUTUwQiwgI0Nsb3ZlIG9yIHNwaWNlCiAgICAgICAgICAgICAgICAgIFE1MEMsICNGcnVpdAogICAgICAgICAgICAgICAgICBRNTBELCAjQ2hvY29sYXRlCiAgICAgICAgICAgICAgICAgIFE1MEUsICNBbGNvaG9saWMgRHJpbmsKICAgICAgICAgICAgICAgICAgUTUwRiwgI0NhbmR5L0Rlc3NlcnRzL090aGVyIFN3ZWV0cwogICAgICAgICAgICAgICAgICBRNTBHLCAjU29tZSBPdGhlciBGbGF2b3IgTm90IExpc3RlZCBIZXJlCiAgICAgICAgICAgICAgICAgIFE1MEggI0kgRGlkIE5vdCBVc2UgRmxhdm9yZWQgVG9iYWNjbyBQcm9kdWN0cyBJbiB0aGUgUGFzdAogICAgICAgICAgICAgICAgICApCgp0YmxfZmlsZXNbWyJueXRzMjAxOCJdXSA8LSB0YmxfZmlsZXNbWyJueXRzMjAxOCJdXSAlPiUKICAgIGRwbHlyOjpzZWxlY3QocHN1LAogICAgICAgICAgICAgICAgICBmaW53Z3QsCiAgICAgICAgICAgICAgICAgIHN0cmF0dW0sCiAgICAgICAgICAgICAgICAgIFExLCAjQWdlCiAgICAgICAgICAgICAgICAgIFEyLCAjU2V4CiAgICAgICAgICAgICAgICAgIFEzLCAjR3JhZGUKICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIkUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZ25vcmUuY2FzZSA9IEZBTFNFKSwKICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIkMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZ25vcmUuY2FzZSA9IEZBTFNFKSwKICAgICAgICAgICAgICAgICAgUTUwQSwgI01lbnRob2wgIyBXaGF0IGZsYXZvcnMgb2YgdG9iYWNjbyBwcm9kdWN0cyBoYXZlIHlvdSB1c2VkIGluIHRoZSBwYXN0IDMwIGRheXM/IChTZWxlY3Qgb25lIG9yIG1vcmUpCiAgICAgICAgICAgICAgICAgIFE1MEIsICNDbG92ZSBvciBzcGljZQogICAgICAgICAgICAgICAgICBRNTBDLCAjRnJ1aXQKICAgICAgICAgICAgICAgICAgUTUwRCwgI0Nob2NvbGF0ZQogICAgICAgICAgICAgICAgICBRNTBFLCAjQWxjb2hvbGljIERyaW5rCiAgICAgICAgICAgICAgICAgIFE1MEYsICNDYW5keS9EZXNzZXJ0cy9PdGhlciBTd2VldHMKICAgICAgICAgICAgICAgICAgUTUwRywgI1NvbWUgT3RoZXIgRmxhdm9yIE5vdCBMaXN0ZWQgSGVyZQogICAgICAgICAgICAgICAgICBRNTBIICNJIERpZCBOb3QgVXNlIEZsYXZvcmVkIFRvYmFjY28gUHJvZHVjdHMgSW4gdGhlIFBhc3QKICAgICAgICAgICAgICAgICAgKQoKdGJsX2ZpbGVzW1sibnl0czIwMTkiXV0gPC0gdGJsX2ZpbGVzW1sibnl0czIwMTkiXV0gJT4lCiAgICBkcGx5cjo6c2VsZWN0KHBzdSwKICAgICAgICAgICAgICAgICAgZmlud2d0LAogICAgICAgICAgICAgICAgICBzdHJhdHVtLAogICAgICAgICAgICAgICAgICBRMSwgI0FnZQogICAgICAgICAgICAgICAgICBRMiwgI1NleAogICAgICAgICAgICAgICAgICBRMywgI0dyYWRlCiAgICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJFIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JlLmNhc2UgPSBGQUxTRSksCiAgICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJDIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JlLmNhc2UgPSBGQUxTRSksCiAgICAgICAgICAgICAgICAgIFE0MCwgI0JyYW5kLCBlLWNpZ2FyZXR0ZXMKICAgICAgICAgICAgICAgICAgUTYyQSwgI01lbnRob2wgIyBXaGF0IGZsYXZvcnMgb2YgdG9iYWNjbyBwcm9kdWN0cyBoYXZlIHlvdSB1c2VkIGluIHRoZSBwYXN0IDMwIGRheXM/IChTZWxlY3Qgb25lIG9yIG1vcmUpCiAgICAgICAgICAgICAgICAgIFE2MkIsICNDbG92ZSBvciBzcGljZQogICAgICAgICAgICAgICAgICBRNjJDLCAjRnJ1aXQgCiAgICAgICAgICAgICAgICAgIFE2MkQsICNDaG9jb2xhdGUKICAgICAgICAgICAgICAgICAgUTYyRSwgI0FsY29ob2xpYyBEcmluawogICAgICAgICAgICAgICAgICBRNjJGLCAjQ2FuZHkvRGVzc2VydHMvT3RoZXIgU3dlZXRzCiAgICAgICAgICAgICAgICAgIFE2MkcsICNTb21lIE90aGVyIEZsYXZvciBOb3QgTGlzdGVkIEhlcmUgCiAgICAgICAgICAgICAgICAgICkKCmBgYAoKQSBkaXJlY3Rvcnkgd2FzIGNyZWF0ZWQgdXNpbmcgdGhlIGJhc2UgYGRpci5jcmVhdGUoKWAgZnVuY3Rpb24gY2FsbGVkIGBkYXRhX3JlZHVjZWRgIGZvciB0aGUgY3N2IGZpbGVzLiAKTmV3IGNzdiBmaWxlcyB3ZXJlIGNyZWF0ZWQgZm9yIGVhY2ggb2YgdGhlIHRibHMgaW4gdGhlIGxpc3QgdXNpbmcgdGhlIGB3cml0ZV9jc3YoKWAgZnVuY3Rpb24gb2YgdGhlIGByZWFkcmAgcGFja2FnZS4KVGhpcyB3YXMgZG9uZSBhbGwgYXQgb25jZSB1c2luZyB0aGUgYmFzZSBgbWFwcHkoKWAgZnVuY3Rpb24uCgpgYGB7ciwgZXZhbCA9IEZBTFNFfQojIApkaXIuY3JlYXRlKCJkb2NzL2RhdGFfcmVkdWNlZCIpCgptYXBwbHkod3JpdGVfY3N2LCB0YmxfZmlsZXMsIHBhdGg9aGVyZShwYXN0ZTAoImRvY3MvZGF0YV9yZWR1Y2VkLyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lcyh0YmxfZmlsZXMpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcuY3N2JykpCiAgICAgKQoKI3RyeWluZyB0byB1c2UgbWFwLi4uCnRibF9maWxlcyAlPiUKbWFwKH53cml0ZV9jc3YoLiAsIHBhdGg9cGFzdGUwKCJkb2NzL2RhdGFfcmVkdWNlZDIvbnl0cyIsIHB1bGwoeWVhcilbWzFdXSwgIixjc3YiKSkpCgoKICAgIHRibF9maWxlcyAlPiUKbWFwKH53cml0ZV9jc3YoLiAsIHBhdGg9cGFzdGUwKCJkb2NzL2RhdGFfcmVkdWNlZDIvbnl0cyIsIG5hbWVzKC4pLCAiLGNzdiIpKSkKCiAgIApgYGAKCjwvZGV0YWlscz4KCgoKTm93IHdlIHdpbGwgc2hvdyBob3cgdG8gcmVhZCBpbiB0aGUgZGF0YSBmcm9tIHRoZSBmaXZlIGNzdiBmaWxlcyB0aGF0IHdlcmUgY3JlYXRlZCBmcm9tIHRoZSBmaXZlIGRpZmZlcmVudCBleGNlbCBmaWxlcy4KCiMjIyBSZWFkaW5nIGluIHRoZSBDU1YgZmlsZXMKKioqCgpgYGB7ciwgZWNobz1GQUxTRSwgaW5jbHVkZT1GQUxTRX0Kc3RhcnRfdGltZSA8LSBTeXMudGltZSgpCgplbmRfdGltZSA8LSBTeXMudGltZSgpCgp0ZXN0X3RpbWUgPC0gZW5kX3RpbWUgLSBzdGFydF90aW1lCgp0aW1lX21lc3NhZ2UgPC0gcGFzdGUoIkR1cmF0aW9uIG9mIGRhdGEgaW1wb3J0OiIsCiAgICAgIHJvdW5kKGFzLm51bWVyaWModGVzdF90aW1lKSAsMyksCiAgICAgIHVuaXRzKHRlc3RfdGltZSkKICAgICAgKQpgYGAKCgpgYGB7cn0Kbnl0c19kYXRhIDwtIGxpc3QuZmlsZXMoaGVyZTo6aGVyZSgpLHJlY3Vyc2l2ZSA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gIiouY3N2IiklPiUKICBtYXAofnJlYWRfY3N2KC4pKQoKCm55dHNfZGF0YV9uYW1lcyA8LSBsaXN0LmZpbGVzKHJlY3Vyc2l2ZSA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gIiouY3N2IiklPiUKICBzdHJfZXh0cmFjdCgibnl0c1syXVswXVsxXVs1LTldIikKCm5hbWVzKG55dHNfZGF0YSkgPC0gbnl0c19kYXRhX25hbWVzCmBgYAoKCiMjICoqRGF0YSBFeHBsb3JhdGlvbiBhbmQgV3JhbmdsaW5nKioKKioqIAoKCiMjIyBSZW5hbWluZyB2YXJpYWJsZXMgIAoqKiogCgpIZXJlIGlzIHdoYXQgdGhlIGRhdGEgZm9yIDIwMTUgbG9va3MgbGlrZToKCiMjIyMgey5zY3JvbGxhYmxlIH0KCmBgYHtyfQpnbGltcHNlKG55dHNfZGF0YVtbIm55dHMyMDE1Il1dKQpgYGAKIyMjIwoKQ3VycmVudGx5LCBpdCBpc24ndCB2ZXJ5IGNsZWFyIHdoYXQgbW9zdCBvZiB0aGUgdmFyaWFibGVzIGluZGljYXRlLgoKV2Ugd2FudCB0byByZW5hbWUgdmFyaWFibGVzIGxpa2UgYFFuMWAgdG8gc29tZXRoaW5nIG1vcmUgbWVhbmluZ2Z1bCBsaWtlIGBBZ2VgLgoKVG8gZG8gdGhpcyB3ZSB3aWxsIHVzZSB0aGUgYHJlbmFtZSgpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlLiBUaGUgbmV3IG5hbWUgaXMgYWx3YXlzIGxpc3RlZCBmaXJzdCBiZWZvcmUgdGhlIGA9YC4KYGBge3J9CgpueXRzX2RhdGFbWyJueXRzMjAxNSJdXSA8LSBueXRzX2RhdGFbWyJueXRzMjAxNSJdXSAlPiUKICAgIGRwbHlyOjpyZW5hbWUoQWdlPVFuMSwKICAgICAgICAgICBTZXg9UW4yLAogICAgICAgICAgIEdyYWRlPVFuMykKYGBgCgoKV2UgYWxzbyB3YW50IHRvIHVwZGF0ZSB0aGUgdmFsdWVzIGZvciBhZ2UgYW5kIGdyYWRlLCBzbyB0aGF0IHRoZXkgYXJlIG1vcmUgdW5kZXJzdGFuZGFibGUuIAoKUmVjYWxsIGZyb20gdGhlIGNvZGVib29rIGZvciB0aGlzIHllYXIsIHRoYXQgYWdlIGlzbid0IGxpc3RlZCBpbiB0aGUgd2F5IG9uZSBtaWdodCBleHBlY3Q6CgpgYGB7ciwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIiLCBvdXQud2lkdGggPSAiNjAwIHB4In0KCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJxbjEucG5nIikpCmBgYAoKVGhlIHNhbWUgaXMgdHJ1ZSBmb3IgZ3JhZGU6CgpgYGB7ciwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIiLCBvdXQud2lkdGggPSAiNjAwIHB4In0KCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJncmFkZS5wbmciKSkKYGBgCgoqKlRoaXMgaXMgd2h5IGl0IGlzIHNvIGltcG9ydGFudCB0byBhbHdheXMgY2hlY2sgdGhlIGNvZGVib29rISEqKgoKV2UgYWxzbyBuZWVkIHRvIGFkZCBuZXcgdmFyaWFibGVzIGFib3V0IHVzYWdlIG9mIGJyYW5kcyBhbmQgc3BlY2lmaWMgZmxhdm9ycyBvZiBlLWNpZ3JhdHRlcywgYmVjYXVzZSBhbHRob3VnaCBsYXRlciB5ZWFycyBoYXZlIHF1ZXN0aW9ucyBhYm91dCB0aGlzLCB0aGlzIHllYXIgdW5mb3J0dW5hdGVseSBvbmx5IGhhcyBicm9hZCBxdWVzdGlvbnMgYWJvdXQgZmxhdm9ycy4gRXZlbnR1YWxseSB3ZSB3YW50IHRvIHB1dCB0aGUgZGF0YSBmcm9tIGVhY2ggeWVhciB0b2dldGhlciwgc28gd2UgbmVlZCB0aGUgc2FtZSB2YXJpYWJsZXMgZm9yIGVhY2ggeWVhci4gVGh1cyB3ZSBuZWVkIHRvIGFkZCB2YXJpYWJsZXMgdGhhdCBqdXN0IHNheSBgTkFgIGZvciB0aGUgYnJhbmQgYW5kIGZsYXZvciBkYXRhIGZvciB0aGlzIHllYXIuCgpUbyBjaGFuZ2UgdGhlIGV4aXN0aW5nIHZhcmlhYmxlcyBhbmQgY3JlYXRlIG5ldyB2YXJpYWJlbHMsIHdlIHdpbGwgdXNlIHRoZSBgbXV0YXRlYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlLgoKYGBge3J9Cm55dHNfZGF0YVtbIm55dHMyMDE1Il1dIDwtIG55dHNfZGF0YVtbIm55dHMyMDE1Il1dICU+JQogIGRwbHlyOjptdXRhdGUoCiAgICAgICAgICAgYnJhbmRfZWNpZz1OQSwKICAgICAgICAgICBtZW50aG9sPU5BLAogICAgICAgICAgIGNsb3ZlX3NwaWNlPU5BLAogICAgICAgICAgIGZydWl0PU5BLAogICAgICAgICAgIGNob2NvbGF0ZT1OQSwKICAgICAgICAgICBhbGNvaG9saWNfZHJpbms9TkEsCiAgICAgICAgICAgY2FuZHlfZGVzc2VydF9zd2VldHM9TkEsCiAgICAgICAgICAgb3RoZXI9TkEsCiAgICAgICAgICAgbm9fdXNlPU5BKSAKYGBgCgoKTm93IHdlIGNhbiBzZWUgaG93IHRoZSBkYXRhIGhhcyBjaGFuZ2VkOgoKIyMjIyB7LnNjcm9sbGFibGUgfQpgYGB7cn0KZHBseXI6OmdsaW1wc2Uobnl0c19kYXRhW1sibnl0czIwMTUiXV0pCmBgYAojIyMjCgoKRm9yIHRoZSBuZXh0IHllYXJzLCB3ZSBkbyBoYXZlIGZsYXZvciBxdWVzdGlvbnMsIGJ1dCBub3QgYSBicmFuZCBxdWVzdGlvbi4gV2UgY2FuIHJlcGxhY2UgdGhlc2UgdmFndWUgcXVlc3Rpb24gbmFtZXMgbGlrZSBgUTUwQWAgd2l0aCB2YWx1ZXMgbGlrZSBgbWVudGhvbGAuICBUaGUgbmV4dCAzIHllYXJzIGhhdmUgdGhlIHNhbWUgc3RydWN0dXJlIGZvciB0aGVzZSBxdWVzdGlvbnMuIFdlIHdpbGwgYWxzbyBjcmVhdGUgYSBicmFuZCB2YXJpYWJsZSB0aGF0IGlzIGp1c3QgYE5BYCB2YWx1ZXMuCgpgYGB7cn0KClVwZGF0ZV9zdXJ2ZXkgPC0gZnVuY3Rpb24oeCkgeyB4ICU+JQogICAgICByZW5hbWUoQWdlPVExLAogICAgICAgICAgIFNleD1RMiwKICAgICAgICAgICBHcmFkZT1RMywKICAgICAgICAgICBtZW50aG9sPVE1MEEsCiAgICAgICAgICAgY2xvdmVfc3BpY2U9UTUwQiwKICAgICAgICAgICBmcnVpdD1RNTBDLAogICAgICAgICAgIGNob2NvbGF0ZT1RNTBELAogICAgICAgICAgIGFsY29ob2xpY19kcmluaz1RNTBFLAogICAgICAgICAgIGNhbmR5X2Rlc3NlcnRfc3dlZXRzPVE1MEYsCiAgICAgICAgICAgb3RoZXI9UTUwRywKICAgICAgICAgICBub191c2U9UTUwSCkgJT4lCiAgICBtdXRhdGUoYnJhbmRfZWNpZz1OQSkKfQoKI2ZldyBvcHRpb25zIHRvIGFwcGx5IHRvIHRoZSBkYXRhOgojbnl0c19kYXRhIDwtbnl0c19kYXRhICU+JSBtYXBfYXQodmFycyhueXRzMjAxNiwgbnl0czIwMTcsIG55dHMyMDE4KSwgVXBkYXRlX3N1cnZleSkKI255dHNfZGF0YSA8LW55dHNfZGF0YSAlPiUgbWFwX2F0KGMoIm55dHMyMDE2IiwgIm55dHMyMDE3IiwgIm55dHMyMDE4IiksIFVwZGF0ZV9zdXJ2ZXkpCm55dHNfZGF0YSA8LW55dHNfZGF0YSAlPiUgbWFwX2F0KHZhcnMoLW55dHMyMDE1LCAtbnl0czIwMTkpLCBVcGRhdGVfc3VydmV5KQpgYGAKClRoZSBmaW5hbCB5ZWFyIGhhcyBhIHNsaWdodGx5IGRpZmZlcmVudCBkYXRhIHN0cnVjdHVyZSAtIEl0IGFjdHVhbGx5IGhhcyBhIGJyYW5kX2VjaWcgdmFyaWFibGUuCgpgYGB7cn0Kbnl0c19kYXRhW1sibnl0czIwMTkiXV0gPC0gbnl0c19kYXRhW1sibnl0czIwMTkiXV0gJT4lCiAgICByZW5hbWUoYnJhbmRfZWNpZz1RNDAsCiAgICAgICAgICAgQWdlPVExLAogICAgICAgICAgIFNleD1RMiwKICAgICAgICAgICBHcmFkZT1RMywKICAgICAgICAgICBtZW50aG9sPVE2MkEsCiAgICAgICAgICAgY2xvdmVfc3BpY2U9UTYyQiwKICAgICAgICAgICBmcnVpdD1RNjJDLAogICAgICAgICAgIGNob2NvbGF0ZT1RNjJELAogICAgICAgICAgIGFsY29ob2xpY19kcmluaz1RNjJFLAogICAgICAgICAgIGNhbmR5X2Rlc3NlcnRfc3dlZXRzPVE2MkYsCiAgICAgICAgICAgb3RoZXI9UTYyRykgJT4lCiAgICBtdXRhdGUobm9fdXNlPSJtaXNzaW5nIikKYGBgCgoKIyMjIFVwZGF0aW5nIFZhbHVlcwoKV2UgYWxzbyAgd2FudCB0byByZXBsYWNlIHRoZSB2YWx1ZSBvZiBgMTlgIGZvciBgQWdlYCB0byBiZSBgIj4xOCJgIGFuZCB0aGUgdmFsdWUgb2YgYDEzYCBmb3IgYEdyYWRlYCB0byBiZSByZXBsYWNlZCB3aXRoIGAiVW5ncmFkZWQvT3RoZXIiYCBBbHNvIGFjY3JvZGluZyB0byB0aGUgY29kZWJvb2tzLCBudW1lcmljIHZhbHVlcyBvZiBgMWAgaW5kaWNhdGUgYSBzdXJ2ZXkgYW5zd2VyIG9mIGBGQUxTRWAsIHdoaWxlIGEgdmFsdWUgb2YgYDJgIGluZGljYXRlcyBgVFJVRWAuIGBTZXhgIG5lZWRzIHRvIGJlIHJlY29kZWQsIGJ1dCBpdCBpcyBhIGJpdCB1bmNsZWFyIGlmIGl0IGlzIGVuY29kZWQgc2xpZ2h0bHkgZGlmZmVyZW50bHkgYWNyb3NzIHllYXJzLgoKCkxldCdzIGNyZWF0ZSBhIGZ1bmN0aW9uIHRvIG1ha2UgYWxsIHRoZXNlIHVwZGF0ZXMgZXhjZXB0IGZvciBgU2V4YDoKYGBge3J9ClVwZGF0ZV92YWx1ZXMgPC0gZnVuY3Rpb24oeCkgeyB4ICU+JQogICAgICBtdXRhdGUoQWdlPWFzLm51bWVyaWMoQWdlKSs4LAogICAgICAgICAgICAgR3JhZGU9YXMubnVtZXJpYyhHcmFkZSkrNSklPiUKICAgICAgbXV0YXRlKEFnZT1hcy5mYWN0b3IoQWdlKSwKICAgICAgICAgR3JhZGU9YXMuZmFjdG9yKEdyYWRlKSwKICAgICAgICAgKSAlPiUKICBtdXRhdGVfYWxsKH4gcmVwbGFjZSguLCAuICVpbiUgYygiKiIsICIqKiIpLCBOQSkpJT4lCiAgbXV0YXRlKEFnZT1yZWNvZGUoQWdlLAogICAgICAgICAgICAgICAgICAgIGAxOWAgPSAiPjE4IiwKICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBHcmFkZT1yZWNvZGUoR3JhZGUsCiAgICAgICAgICAgICAgICAgICAgICBgMTNgID0gIlVuZ3JhZGVkL090aGVyIikpICU+JQogIG11dGF0ZV9hdCh2YXJzKHN0YXJ0c193aXRoKCJFIiwgaWdub3JlLmNhc2UgPSBGQUxTRSksCiAgICAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiQyIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSwKICAgICAgICAgICAgICBsaXN0KH5yZWNvZGUoLiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYDFgID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYDJgID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC5kZWZhdWx0ID0gTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC5taXNzaW5nID0gTkEpKSkKfQoKbnl0c19kYXRhIDwtbnl0c19kYXRhICU+JSBtYXAoLixVcGRhdGVfdmFsdWVzKQoKYGBgCgoKTm93IGxldCdzIHVwZGF0ZSB0aGUgYFNleGAgZW5jb2Rpbmc6CgpJdCdzIGEgYml0IGRpZmZpY3VsdCB0byB0ZWxsIGlmIHRoZSBlbmNvZGluZyB3YXMgdGhlIHNhbWUgYWNyb3NzIHllYXJzLCBzbyBsZXQncyBjaGVjayB1c2luZyB0aGUgYGNvdW50KClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UuCgpBY2NvcmRpbmcgdG8gdGhlIGNvZGVib29rLCB3ZSBzaG91bGQgaGF2ZTogIAoxKSA4LDk1OCBtYWxlcyBpbiAyMDE1IAoyKSAxMCw0MzggbWFsZXMgaW4gMjAxNiAKMykgOCw4ODEgbWFsZXMgaW4gMjAxNyAgCjQpIDEwLDA2OSBtYWxlcyBpbiAyMDE4ICAKNSkgOSw4MDMgbWFsZXMgaW4gMjAxOSAgCgpgYGB7cn0KY291bnRfc2V4IDwtZnVuY3Rpb24oeCl7eCAlPiVjb3VudChTZXgpfQpueXRzX2RhdGEgJT4lIG1hcCguLCBjb3VudF9zZXgpCmBgYAoKClRodXMsIGl0IGxvb2tzIGxpa2UgbWFsZXMgd2VyZSBlbmNvZGVkIGFzIGAxYCBmb3IgZWFjaCB5ZWFyLgoKMSkgOCw5NTggbWFsZXMgaW4gMjAxNSB3aGVyZSAxID0gbWFsZSAgCjIpIDEwLDQzOCBtYWxlcyBpbiAyMDE2IHdoZXJlIDEgPSBtYWxlCjMpIDgsODgxIG1hbGVzIGluIDIwMTcgd2hlcmUgMSA9IG1hbGUgIAo0KSAxMCwwNjkgbWFsZXMgaW4gMjAxOCB3aGVyZSAxID0gbWFsZQo1KSA5LDgwMyBtYWxlcyBpbiAyMDE5IHdoZXJlIDEgPSBtYWxlCgoKYGBge3J9CgogIFVwZGF0ZV9zZXggPC0gZnVuY3Rpb24oeCl7eCAlPiUKICAgICAgbXV0YXRlKFNleCA9IGFzLmZhY3RvcihTZXgpKSAlPiUKICAgICAgICAgbXV0YXRlKFNleCA9IHJlY29kZShTZXgsCiAgICAgICAgICAgICAgICAgICAgICBgMWA9ICJtYWxlIiwKICAgICAgICAgICAgICAgICAgICAgIGAyYCA9ICJmZW1hbGUiKSkKICB9CgpueXRzX2RhdGEgPC1ueXRzX2RhdGEgJT4lIG1hcCguLCBVcGRhdGVfc2V4KQpjb3VudF9zZXggPC1mdW5jdGlvbih4KXt4ICU+JWNvdW50KFNleCl9Cm55dHNfZGF0YSAlPiUgbWFwKC4sIGNvdW50X3NleCkKCmBgYAoKTG9va3MgZ29vZCEKCgoKVGhlIHllYXJzICgyMDE2LTIwMTkpIHRoYXQgaGF2ZSBmbGF2b3JzIGFsc28gbmVlZCB0aGUgZmxhdm9yIGRhdGEgdG8gYmUgbG9naWNhbDoKCmBgYHtyfQpVcGRhdGVfZmxhdm9ycyA8LSBmdW5jdGlvbih4KXt4ICU+JQogICBtdXRhdGVfYXQodmFycyhtZW50aG9sOm5vX3VzZSksCiAgICAgICAgICAgICAgbGlzdCh+cmVjb2RlKC4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGAxYCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgLmRlZmF1bHQgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIC5taXNzaW5nID0gRkFMU0UpKSkgfQoKbnl0c19kYXRhICA8LSBueXRzX2RhdGEgICU+JSBtYXBfYXQodmFycygtbnl0czIwMTUpLCBVcGRhdGVfZmxhdm9ycykKCmBgYAoKCk5vdyB0aGVyZSBhcmUganVzdCBhIGZldyBjaGFuZ2VzIG5lZWRlZCB0aGF0IGFyZSBzcGVjaWZpYyB0byAyMDE5OgoKYGBge3J9Cm55dHNfZGF0YVtbIm55dHMyMDE5Il1dIDwtIG55dHNfZGF0YVtbIm55dHMyMDE5Il1dICU+JQogIG11dGF0ZV9hbGwofiByZXBsYWNlKC4sIC4gJWluJSBjKCIuTiIsIi5TIiwiLloiKSwgTkEpKSAlPiUKICBtdXRhdGUocHN1PWFzLmNoYXJhY3Rlcihwc3UpKSAlPiUKICBtdXRhdGUoYnJhbmRfZWNpZyA9IHJlY29kZShicmFuZF9lY2lnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgMWAgPSAiT3RoZXIiLCAjbGV2ZWxzIDEsOCBjb21iaW5lZCB0byBgT3RoZXJgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgMmAgPSAiQmx1IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYDNgID0gIkpVVUwiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgNGAgPSAiTG9naWMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgNWAgPSAiTWFya1RlbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGA2YCA9ICJOSk9ZIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYDdgID0gIlZ1c2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgOGAgPSAiT3RoZXIiKSkKCmBgYAoKR3JlYXQhIE5vdyB3ZSBoYXZlIGFsbCB0aGUgc2FtZSB2YXJpYWJsZXMgYW5kIG91ciB2YWx1ZXMgZG9uJ3QgbmVlZCB0byBiZSBoYW5kbGVkIGFueSBkaWZmZXJlbnRseSBmb3IgYW55IG9mIHRoZSB5ZWFycy4gVGh1cyB3ZSBjYW4gY29tYmluZSB0aGUgZGF0YSBhY3Jvc3MgeWVhcnMuCgpgYGB7cn0Kbnl0c19kYXRhIDwtIG55dHNfZGF0YSAlPiUKICBtYXBfZGYoYmluZF9yb3dzLCAuaWQgPSAieWVhciIpCgpoZWFkKG55dHNfZGF0YSkKYGBgCgpMb29rcyBsaWtlIHdlIGp1c3QgbmVlZCB0byByZW1vdmUgYCJueXRzImAgZnJvbSB0aGUgeWVhciB2YXJpYWJsZSB0aGF0IHdlIGNyZWF0ZWQgZnJvbSB0aGUgbmFtZXMgb2YgdGhlIHRpYmJsZXMgaW4gb3VyIGxpc3QuCgpgYGB7cn0Kbnl0c19kYXRhIDwtIG55dHNfZGF0YSAlPiUKICBtdXRhdGUoeWVhcj1hcy5udW1lcmljKHN0cl9yZW1vdmUoeWVhciwibnl0cyIpKSkKCmBgYAoKSGVyZSBpcyBvdXIgY2xlYW4gYW5kIHdyYW5nbGVkIGRhdGE6CmBgYHtyfQpoZWFkKG55dHNfZGF0YSkKCmBgYAoKPHN0eWxlPgpkaXYuYmx1ZSB7IGJhY2tncm91bmQtY29sb3I6I2U2ZjBmZjsgYm9yZGVyLXJhZGl1czogNXB4OyBwYWRkaW5nOiAyMHB4O30KPC9zdHlsZT4KPGRpdiBjbGFzcyA9ICJibHVlIj4KClJlbWluZGVyOiBDdXJyZW50IHVzZXJzIGFyZSBhIHN1YnNldCBvZiBldmVyIHVzZXJzLiAKCjwvZGl2PgoKCgoKCgojIyAqKkRhdGEgVmlzdWFsaXphdGlvbioqCioqKiAKCiMjIyBRdWVzdGlvbiAxIAoKRm9yIGxvdHMgb2YgcGl2b3RfbG9uZ2VyKCkgdGhhdCBhcmUgdGhlIHNhbWUuLi4gY2FuIHVzZSBwaXZvdF9sb25nZXJfc3BlYygpCgpzcGVjIDwtIHJlbGlnX2luY29tZSAlPiUgYnVpbGRfbG9uZ2VyX3NwZWMoCiAgY29scyA9IC1yZWxpZ2lvbiwKICBuYW1lc190byA9ICJpbmNvbWUiLAogIHZhbHVlc190byA9ICJjb3VudCIKKQpwaXZvdF9sb25nZXJfc3BlYyhyZWxpZ19pbmNvbWUsIHNwZWMpCgpCdXQgbmVlZCB0byBkZWNpZGUgaWYgd2UgYXJlIGdvaW5nIHRvIGNyZWF0ZSBzb21lIG5ldyBkYXRhIGZyYW1lcy4uLgoKYGBge3J9CnBsb3QxIDwtIG55dHNfZGF0YSAlPiUKICAgIG11dGF0ZSh0b2JhY2NvX3N1bV9ldmVyID0gc2VsZWN0KC4sIHN0YXJ0c193aXRoKCJFIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpLAogICAgICAgICAgIHRvYmFjY29fc3VtX2N1cnJlbnQgPSBzZWxlY3QoLiwgc3RhcnRzX3dpdGgoIkMiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSkpICU+JQogICAgbXV0YXRlKHRvYmFjY29fZXZlciA9IGNhc2Vfd2hlbih0b2JhY2NvX3N1bV9ldmVyID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvYmFjY29fc3VtX2V2ZXIgPT0wIH4gRkFMU0UpLAogICAgICAgICAgIHRvYmFjY29fY3VycmVudCA9IGNhc2Vfd2hlbih0b2JhY2NvX3N1bV9jdXJyZW50ID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvYmFjY29fc3VtX2N1cnJlbnQgPT0wIH4gRkFMU0UpKSAlPiUKICAgIGdyb3VwX2J5KHllYXIpICU+JQogICAgc3VtbWFyaXNlKHRvYmFjY29fZXZlcl95ZWFyPShzdW0odG9iYWNjb19ldmVyLCBuYS5ybSA9IFRSVUUpKjEwMCkvCiAgICAgICAgICAgICAgICBzdW0oIWlzLm5hKHRvYmFjY29fZXZlcikpLAogICAgICAgICAgICAgIHRvYmFjY29fY3VycmVudF95ZWFyPShzdW0odG9iYWNjb19jdXJyZW50LCBuYS5ybSA9IFRSVUUpKjEwMCkvCiAgICAgICAgICAgICAgICBzdW0oIWlzLm5hKHRvYmFjY29fY3VycmVudCkpKSAlPiUKICAgIHJlbmFtZSgiRXZlciI9dG9iYWNjb19ldmVyX3llYXIsCiAgICAgICAgICAgIkN1cnJlbnQiPXRvYmFjY29fY3VycmVudF95ZWFyKSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IC15ZWFyLCBuYW1lc190byA9ICJVc2VyIiwgdmFsdWVzX3RvID0gIlBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHMiKSU+JQogICAgZ2dwbG90KGFlcyh4PXllYXIseT1gUGVyY2VudGFnZSBvZiBzdHVkZW50c2AsIGxpbmV0eXBlPVVzZXIpKSArCiAgICBnZW9tX2xpbmUoKSArIAogIGdlb21fcG9pbnQoc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIHNjYWxlX2xpbmV0eXBlX21hbnVhbCh2YWx1ZXMgPSBjKDIsMSkpICsKICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCw3MCxieT0xMCksCiAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2VxKDAsNzAsYnk9MTApLAogICAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMCw3MCkpICsKICAgIHRoZW1lX21pbmltYWwoKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogICAgbGFicyh0aXRsZSA9ICJIb3cgZG9lcyBuaWNvdGluZSB1c2UgdmFyeSBvdmVyIHRoZSB5ZWFycz8iLAogICAgICAgICBzdWJ0aXRsZSA9ICJDdXJyZW50IGFuZCBldmVyIHVzZXJzIG9mIG5pY290aW5lIHByb2R1Y3RzIiwKICAgICAgICAgeSA9ICIlIG9mIHN0dWRlbnRzIikKCnBsb3QxIApgYGAKCiMjIyBRdWVzdGlvbiAyCgpgYGB7cn0KcGxvdDIgPC0gbnl0c19kYXRhICU+JQogICAgZ3JvdXBfYnkoeWVhciwKICAgICAgICAgICAgIFNleCkgJT4lCiAgICBzdW1tYXJpc2UoRUVMQ0lHVF95ZWFyPShzdW0oRUVMQ0lHVCwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgICAgc3VtKCFpcy5uYShFRUxDSUdUKSksCiAgICAgICAgICAgICAgQ0VMQ0lHVF95ZWFyPShzdW0oQ0VMQ0lHVCwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgICAgc3VtKCFpcy5uYShDRUxDSUdUKSkpICU+JSAKICAgIGZpbHRlcighaXMubmEoU2V4KSkgJT4lCiAgICByZW5hbWUoIkUtY2lnYXJldHRlcywgRXZlciI9RUVMQ0lHVF95ZWFyLAogICAgICAgICAgICJFLWNpZ2FyZXR0ZXMsIEN1cnJlbnQiPUNFTENJR1RfeWVhcikgJT4lCiAgI2NvbnZlcnRpbmcgYWxsIGNvbHVtbnMgYmV0d2VlbiBhbmQgaW5jbHVkaW5nIGBFLWNpZ2FyZXR0ZXMsIEV2ZXJgIGFuZCBgRS1jaWdhcmV0dGVzLCBDdXJyZW50YCBpbnRvIG9uZSBjb2x1bW4gY2FsbGVkIGNhdGVnb3J5CiAgICBwaXZvdF9sb25nZXIoY29scyA9IGBFLWNpZ2FyZXR0ZXMsIEV2ZXJgOmBFLWNpZ2FyZXR0ZXMsIEN1cnJlbnRgLCBuYW1lc190byA9ICJDYXRlZ29yeSIsIHZhbHVlc190byA9ICJQZXJjZW50YWdlIG9mIHN0dWRlbnRzIiklPiUKICAgIG11dGF0ZShVc2VyID0gY2FzZV93aGVuKENhdGVnb3J5ID09ICJFLWNpZ2FyZXR0ZXMsIEV2ZXIiIH4gIkV2ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2F0ZWdvcnkgPT0gIkUtY2lnYXJldHRlcywgQ3VycmVudCIgfiAiQ3VycmVudCIpKSAlPiUKICAgICMgbXV0YXRlKFNleCA9IGNhc2Vfd2hlbihmZW1hbGUgPT0gVFJVRSB+ICJGZW1hbGVzIiwKICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVtYWxlID09IEZBTFNFIH4gIk1hbGVzIikpICU+JQogICAgZ2dwbG90KGFlcyh4PXllYXIseT1gUGVyY2VudGFnZSBvZiBzdHVkZW50c2AsIGNvbG9yPVNleCwgbGluZXR5cGU9VXNlcikpICsKICAgIGdlb21fbGluZSgpICsgCiAgZ2VvbV9wb2ludChzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgc2NhbGVfbGluZXR5cGVfbWFudWFsKHZhbHVlcyA9IGMoMiwxKSkgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCksCiAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICAgIGxhYnModGl0bGUgPSAiSG93IGRvIHZhcGluZyByYXRlcyBjb21wYXJlIGJldHdlZW4gbWFsZXMgYW5kIGZlbWFsZXM/IiwKICAgICAgICAgc3VidGl0bGUgPSAiQ3VycmVudCBhbmQgZXZlciB1c2VycyBieSBnZW5kZXIiLAogICAgICAgICB5ID0gIiUgb2Ygc3R1ZGVudHMiKQoKcGxvdDIKYGBgCgojIyMgUXVlc3Rpb24gMwoKV2hhdCB2YXBpbmcgYnJhbmRzIGFuZCBmbGF2b3JzIGFwcGVhciB0byBiZSB1c2VkIHRoZSBtb3N0IGZyZXF1ZW50bHk/CgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmNhcD0iSHVhbmcgSiwgRHVhbiBaLCBLd29rIEosIGV0IGFsLiBUb2IgQ29udHJvbCAyMDE5OzI4OjE0NuKAkzE1MS4iLCBvdXQud2lkdGggPSAnMTAwJSd9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJIdWFuZ0pfRHVhblpfS3dva0pfZXRfYWxfVG9iYWNjb0NvbnRyb2xfRmlndXJlMS5wbmciKSkKYGBgCgpbUGFwZXJdKGh0dHBzOi8vdG9iYWNjb2NvbnRyb2wuYm1qLmNvbS9jb250ZW50L3RvYmFjY29jb250cm9sLzI4LzIvMTQ2LmZ1bGwucGRmKQoKCmBgYHtyfQpwbG90MyA8LSBueXRzX2RhdGEgJT4lCiAgICBmaWx0ZXIoeWVhcj09MjAxOSkgJT4lCiAgICBncm91cF9ieShicmFuZF9lY2lnKSAlPiUKICAgIGZpbHRlcighaXMubmEoYnJhbmRfZWNpZykpICU+JQogICAgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQogICAgbXV0YXRlKHRvdGFsID0gc3VtKG4pLAogICAgICAgICAgIFBlcmNlbnQgPSBuKjEwMC90b3RhbCkgJT4lCiAgICBtdXRhdGUoYnJhbmRfZWNpZyA9IGZjdF9yZW9yZGVyKGJyYW5kX2VjaWcsIGRlc2MoUGVyY2VudCkpKSAlPiUKICAgIGdncGxvdChhZXMoeD1icmFuZF9lY2lnLHk9UGVyY2VudCwgZmlsbD1icmFuZF9lY2lnKSkgKwogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSArCiAgICB0aGVtZV9taW5pbWFsKCkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksCiAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICAgIGxhYnModGl0bGUgPSAiV2hhdCB2YXBpbmcgYnJhbmRzIGFwcGVhciB0byBiZSB1c2VkIHRoZSBtb3N0IGZyZXF1ZW50bHk/IiwKICAgICAgICAgc3VidGl0bGUgPSAiQnJhbmQgb2YgZS1jaWdhcmV0dGUgbW9zdCBmcmVxdWVudGx5IHVzZWQgaW4gdGhlIGxhc3QgMzAgZGF5cyAoMjAxOSkiLAogICAgICAgICB5ID0gIiUgb2YgZS1jaWdhcmV0dGUgdXNlcnMgcmVzcG9uZGluZyIpCgpwbG90MwpgYGAKCmBgYHtyfQpwbG90NCA8LSBueXRzX2RhdGEgJT4lCiAgZmlsdGVyKHllYXIhPTIwMTUpICU+JQogIGdyb3VwX2J5KHllYXIpICU+JQogIHN1bW1hcmlzZShNZW50aG9sPShzdW0obWVudGhvbCwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgICAgc3VtKCFpcy5uYShtZW50aG9sKSksCiAgICAgICAgICAgICAgYENsb3ZlIG9yIFNwaWNlYD0oc3VtKGNsb3ZlX3NwaWNlLCBuYS5ybSA9IFRSVUUpKjEwMCkvCiAgICAgICAgICAgICAgICBzdW0oIWlzLm5hKGNsb3ZlX3NwaWNlKSksCiAgICAgICAgICAgICAgYEZydWl0YD0oc3VtKGZydWl0LCBuYS5ybSA9IFRSVUUpKjEwMCkvCiAgICAgICAgICAgICAgICBzdW0oIWlzLm5hKGZydWl0KSksCiAgICAgICAgICAgICAgYENob2NvbGF0ZWA9KHN1bShjaG9jb2xhdGUsIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICAgIHN1bSghaXMubmEoY2hvY29sYXRlKSksCiAgICAgICAgICAgICAgYEFsY29ob2xpYyBEcmlua2A9KHN1bShhbGNvaG9saWNfZHJpbmssIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICAgIHN1bSghaXMubmEoYWxjb2hvbGljX2RyaW5rKSksCiAgICAgICAgICAgICAgYENhbmR5L0Rlc3NlcnRzL1N3ZWV0c2A9KHN1bShjYW5keV9kZXNzZXJ0X3N3ZWV0cywgbmEucm0gPSBUUlVFKSoxMDApL3N1bSghaXMubmEoY2FuZHlfZGVzc2VydF9zd2VldHMpKSkgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAteWVhciwgbmFtZXNfdG8gPSAiUGVyY2VudGFnZSBvZiBzdHVkZW50cyIsIHZhbHVlc190byA9ICJGbGF2b3IiKSAlPiUKCiAgZ2dwbG90KGFlcyh4PXllYXIsIHk9YFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgLCBjb2xvcj1GbGF2b3IpKSArCiAgZ2VvbV9saW5lKCkgKwogIGdlb21fcG9pbnQoc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSwKICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkgKyAKICBsYWJzKHRpdGxlID0gIldoYXQgZmxhdm9ycyBhcHBlYXIgdG8gYmUgdXNlZCB0aGUgbW9zdCBmcmVxdWVudGx5IGluIG5pY290aW5lIHByb2R1Y3RzPyIsCiAgICAgICBzdWJ0aXRsZSA9ICJGbGF2b3JzIG9mIHRvYmFjY28gcHJvZHVjdHMgdXNlZCBpbiB0aGUgcGFzdCAzMCBkYXlzIikKCnBsb3Q0IApgYGAKCmBgYHtyfQpwbG90NSA8LSBueXRzX2RhdGEgJT4lCiAgZmlsdGVyKHllYXIhPTIwMTUpICU+JQogIGZpbHRlcihtZW50aG9sPT1UUlVFfAogICAgICAgICAgIGNsb3ZlX3NwaWNlPT1UUlVFfAogICAgICAgICAgIGZydWl0PT1UUlVFfAogICAgICAgICAgIGNob2NvbGF0ZT09VFJVRXwKICAgICAgICAgICBhbGNvaG9saWNfZHJpbms9PVRSVUV8CiAgICAgICAgICAgY2FuZHlfZGVzc2VydF9zd2VldHM9PVRSVUV8CiAgICAgICAgICAgb3RoZXI9PVRSVUUpICU+JQogIG11dGF0ZShlY2lnX3N1bV9ldmVyID0gc2VsZWN0KC4sIEVFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpLAogICAgICAgICAgIGVjaWdfc3VtX2N1cnJlbnQgPSBzZWxlY3QoLiwgQ0VMQ0lHVCkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSksCiAgICAgICAgICAgbm9uX2VjaWdfc3VtX2V2ZXIgPSBzZWxlY3QoLiwgc3RhcnRzX3dpdGgoIkUiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSkgJT4lCiAgICAgICAgICAgICAgIHNlbGVjdCguLC1FRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICBub25fZWNpZ19zdW1fY3VycmVudCA9IHNlbGVjdCguLCBzdGFydHNfd2l0aCgiQyIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSAlPiUKICAgICAgICAgICAgICAgc2VsZWN0KC4sLUNFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpKSAlPiUKICAgIG11dGF0ZShlY2lnX2V2ZXIgPSBjYXNlX3doZW4oZWNpZ19zdW1fZXZlciA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlY2lnX3N1bV9ldmVyID09MCB+IEZBTFNFKSwKICAgICAgICAgICBlY2lnX2N1cnJlbnQgPSBjYXNlX3doZW4oZWNpZ19zdW1fY3VycmVudCA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlY2lnX3N1bV9jdXJyZW50ID09MCB+IEZBTFNFKSwKICAgICAgICAgICBub25fZWNpZ19ldmVyID0gY2FzZV93aGVuKG5vbl9lY2lnX3N1bV9ldmVyID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbl9lY2lnX3N1bV9ldmVyID09MCB+IEZBTFNFKSwKICAgICAgICAgICBub25fZWNpZ19jdXJyZW50ID0gY2FzZV93aGVuKG5vbl9lY2lnX3N1bV9jdXJyZW50ID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbl9lY2lnX3N1bV9jdXJyZW50ID09MCB+IEZBTFNFKSkgJT4lCiAgbXV0YXRlKGVjaWdfb25seV9ldmVyID0gY2FzZV93aGVuKGVjaWdfZXZlciA9PSBUUlVFICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub25fZWNpZ19ldmVyID09RkFMU0UgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gRkFMU0UpLAogICAgICAgICAgIGVjaWdfb25seV9jdXJyZW50ID0gY2FzZV93aGVuKGVjaWdfY3VycmVudCA9PSBUUlVFICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbl9lY2lnX2V2ZXIgPT1GQUxTRSB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiBGQUxTRSksCiAgICAgICAgICAgbm9uX2VjaWdfb25seV9ldmVyID0gY2FzZV93aGVuKG5vbl9lY2lnX2V2ZXIgPT0gVFJVRSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWNpZ19ldmVyID09RkFMU0UgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gRkFMU0UpLAogICAgICAgICAgIG5vbl9lY2lnX29ubHlfY3VycmVudCA9IGNhc2Vfd2hlbihub25fZWNpZ19jdXJyZW50ID09IFRSVUUgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVjaWdfZXZlciA9PUZBTFNFIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IEZBTFNFKSkgJT4lCiAgbXV0YXRlKEdyb3VwID0gY2FzZV93aGVuKGVjaWdfb25seV9ldmVyPT1UUlVFIHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlY2lnX29ubHlfY3VycmVudD09VFJVRSB+ICJPbmx5IGUtY2lnYXJldHRlcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICBub25fZWNpZ19vbmx5X2V2ZXI9PVRSVUUgfAogICAgICAgICAgICAgICAgICAgICAgICAgICBub25fZWNpZ19vbmx5X2N1cnJlbnQ9PVRSVUUgfiAiT25seSBvdGhlciBwcm9kdWN0cyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiQm90aCIpKSAlPiUKICBmaWx0ZXIoR3JvdXAhPSJCb3RoIikgJT4lCiAgZ3JvdXBfYnkoeWVhciwgR3JvdXApICU+JQogIHN1bW1hcmlzZShgTWVudGhvbGA9KHN1bShtZW50aG9sLCBuYS5ybSA9IFRSVUUpKjEwMCkvCiAgICAgICAgICAgICAgc3VtKCFpcy5uYShtZW50aG9sKSksCiAgICAgICAgICAgICAgYENsb3ZlIG9yIFNwaWNlYD0oc3VtKGNsb3ZlX3NwaWNlLCBuYS5ybSA9IFRSVUUpKjEwMCkvCiAgICAgICAgICAgICAgc3VtKCFpcy5uYShjbG92ZV9zcGljZSkpLAogICAgICAgICAgICAgIGBGcnVpdGA9KHN1bShmcnVpdCwgbmEucm0gPSBUUlVFKSoxMDApL3N1bSghaXMubmEoZnJ1aXQpKSwKICAgICAgICAgICAgICBgQ2hvY29sYXRlYD0oc3VtKGNob2NvbGF0ZSwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgIHN1bSghaXMubmEoY2hvY29sYXRlKSksCiAgICAgICAgICAgICAgYEFsY29ob2xpYyBEcmlua2A9KHN1bShhbGNvaG9saWNfZHJpbmssIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICBzdW0oIWlzLm5hKGFsY29ob2xpY19kcmluaykpLAogICAgICAgICAgICAgIGBDYW5keS9EZXNzZXJ0cy9Td2VldHNgPShzdW0oY2FuZHlfZGVzc2VydF9zd2VldHMsIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICBzdW0oIWlzLm5hKGNhbmR5X2Rlc3NlcnRfc3dlZXRzKSksCiAgICAgICAgICAgIGBPdGhlcmA9KHN1bShvdGhlciwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgIHN1bSghaXMubmEob3RoZXIpKSwKICAgICAgICAgICAgUmVzcG9uZGVudHM9bigpKSAlPiUKICAjY29udmVydGluZyBhbGwgY29sdW1ucyBiZXR3ZWVuIGFuZCBpbmNsdWRpbmcgTWVudGhvbCBhbmQgT3RoZXIgdG8gb25lIGNvbHVtbiBjYWxsZWQgRmxhdm9yCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBNZW50aG9sOk90aGVyLCBuYW1lc190byA9ICJGbGF2b3IiLCB2YWx1ZXNfdG8gPSAiUGVyY2VudGFnZSBvZiBzdHVkZW50cyIpICU+JQogIGZpbHRlcighaXMubmEoYFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgKSwKICAgICAgICAgRmxhdm9yIT0iT3RoZXIiKSAlPiUKICBncm91cF9ieShGbGF2b3IpICU+JQogIG11dGF0ZShhZmZpcm1hdGl2ZT0oUmVzcG9uZGVudHMgKiBgUGVyY2VudGFnZSBvZiBzdHVkZW50c2ApLzEwMCkgJT4lCiAgbXV0YXRlKGZsYXZvcl9tZWFuID0gc3VtKGFmZmlybWF0aXZlKS9zdW0oUmVzcG9uZGVudHMpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKGZsYXZvcl9tZWFuX3JhbmsgPSBkZW5zZV9yYW5rKGZsYXZvcl9tZWFuKSwKICAgICAgICAgRmxhdm9yID0gZmN0X3Jlb3JkZXIoRmxhdm9yLCBmbGF2b3JfbWVhbl9yYW5rKSkgJT4lCiAgZ2dwbG90KGFlcyh4PXllYXIsIHk9YFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgLCBjb2xvcj1Hcm91cCkpICsKICBmYWNldF93cmFwKC5+Rmxhdm9yLG5jb2w9MykgKwogIGdlb21fbGluZSgpICsgCiAgZ2VvbV9wb2ludChzaG93LmxlZ2VuZCA9IEZBTFNFKSArIAogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpICsgCiAgbGFicyh0aXRsZSA9ICJBbW9uZyB1c2VycyBvZiBvbmx5IG9uZSB0eXBlIG9mIHByb2R1Y3QsIHdoYXQgdmFwaW5nIGZsYXZvcnMgYXBwZWFyIHRvIGJlIHVzZWQgdGhlIG1vc3QgZnJlcXVlbnRseT8iLAogICAgICAgc3VidGl0bGUgPSAiUGVyY2VudCByZXBvcnRpbmcgb25seSBlLWNpZ2FyZXR0ZSB1c2UgdnMgb25seSBvdGhlciBuaWNvdGluZSBwcm9kdWN0IHVzZSIpCgpwbG90NQpgYGAKCiMjIyBRdWVzdGlvbiA0CgpIYXZlIHZhcGluZyByYXRlcyBwb3NzaWJseSBpbmZsdWVuY2VkIHRvYmFjY28vbmljb3RpbmUgdXNlPwoKYGBge3J9CnBsb3Q2IDwtIG55dHNfZGF0YSAlPiUKICAgIGdyb3VwX2J5KHllYXIpICU+JQogICAgc3VtbWFyaXNlKEVDSUdUX3llYXI9KHN1bShFQ0lHVCwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgICAgc3VtKCFpcy5uYShFQ0lHVCkpLAogICAgICAgICAgICAgIEVFTENJR1RfeWVhcj0oc3VtKEVFTENJR1QsIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICAgIHN1bSghaXMubmEoRUVMQ0lHVCkpLAogICAgICAgICAgICAgIENDSUdUX3llYXI9KHN1bShDQ0lHVCwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgICAgc3VtKCFpcy5uYShDQ0lHVCkpLAogICAgICAgICAgICAgIENFTENJR1RfeWVhcj0oc3VtKENFTENJR1QsIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICAgIHN1bSghaXMubmEoQ0VMQ0lHVCkpKSAlPiUKICAgIHJlbmFtZSgiQ2lnYXJldHRlcywgRXZlciI9RUNJR1RfeWVhciwKICAgICAgICAgICAiRS1jaWdhcmV0dGVzLCBFdmVyIj1FRUxDSUdUX3llYXIsCiAgICAgICAgICAgIkNpZ2FyZXR0ZXMsIEN1cnJlbnQiPUNDSUdUX3llYXIsCiAgICAgICAgICAgIkUtY2lnYXJldHRlcywgQ3VycmVudCI9Q0VMQ0lHVF95ZWFyKSAlPiUKICBwaXZvdF9sb25nZXIoY29scz0gLXllYXIsIG5hbWVzX3RvID0gIkNhdGVnb3J5IiwgdmFsdWVzX3RvID0gIlBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHMiKSU+JQogICAgIyBnYXRoZXIoa2V5PUNhdGVnb3J5LAogICAgIyAgICAgICAgdmFsdWU9YFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgLAogICAgIyAgICAgICAgLXllYXIpICU+JQogICAgbXV0YXRlKFVzZXIgPSBjYXNlX3doZW4oQ2F0ZWdvcnkgPT0gIkNpZ2FyZXR0ZXMsIEV2ZXIiIH4gIkV2ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2F0ZWdvcnkgPT0gIkUtY2lnYXJldHRlcywgRXZlciIgfiAiRXZlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDYXRlZ29yeSA9PSAiQ2lnYXJldHRlcywgQ3VycmVudCIgfiAiQ3VycmVudCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDYXRlZ29yeSA9PSAiRS1jaWdhcmV0dGVzLCBDdXJyZW50IiB+ICJDdXJyZW50IikpICU+JQogICAgbXV0YXRlKFByb2R1Y3QgPSBjYXNlX3doZW4oQ2F0ZWdvcnkgPT0gIkNpZ2FyZXR0ZXMsIEV2ZXIiIH4gIkNpZ2FyZXR0ZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2F0ZWdvcnkgPT0gIkUtY2lnYXJldHRlcywgRXZlciIgfiAiRS1jaWdhcmV0dGVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENhdGVnb3J5ID09ICJDaWdhcmV0dGVzLCBDdXJyZW50IiB+ICJDaWdhcmV0dGVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENhdGVnb3J5ID09ICJFLWNpZ2FyZXR0ZXMsIEN1cnJlbnQiIH4gIkUtY2lnYXJldHRlcyIpKSAlPiUKICAgIGdncGxvdChhZXMoeD15ZWFyLHk9YFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgLCBjb2xvcj1Qcm9kdWN0LCBsaW5ldHlwZT1Vc2VyKSkgKwogICAgZ2VvbV9saW5lKCkgKyAKICBnZW9tX3BvaW50KHNob3cubGVnZW5kID0gRkFMU0UpICsKICBzY2FsZV9saW5ldHlwZV9tYW51YWwodmFsdWVzID0gYygyLDEpKSArCiAgICB0aGVtZV9taW5pbWFsKCkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICAgIGxhYnModGl0bGUgPSAiSG93IGRvZXMgZS1jaWdhcmV0dGUgdXNlIGNvbXBhcmUgdG8gY2lnYXJldHRlIHVzZT8iLAogICAgICAgICBzdWJ0aXRsZSA9ICJDdXJyZW50IGFuZCBldmVyIHVzZXJzIG9mIGUtY2lnYXJldHRlcyBhbmQgY2lnYXJldHRlcyIsCiAgICAgICAgIHkgPSAiJSBvZiBzdHVkZW50cyIpCgpwbG90NgpgYGAKCmBgYHtyfQpwbG90NyA8LSBueXRzX2RhdGEgJT4lCiAgICBtdXRhdGUoZWNpZ19zdW1fZXZlciA9IHNlbGVjdCguLCBFRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICBlY2lnX3N1bV9jdXJyZW50ID0gc2VsZWN0KC4sIENFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpLAogICAgICAgICAgIG5vbl9lY2lnX3N1bV9ldmVyID0gc2VsZWN0KC4sIHN0YXJ0c193aXRoKCJFIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpICU+JQogICAgICAgICAgICAgICBzZWxlY3QoLiwtRUVMQ0lHVCkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSksCiAgICAgICAgICAgbm9uX2VjaWdfc3VtX2N1cnJlbnQgPSBzZWxlY3QoLiwgc3RhcnRzX3dpdGgoIkMiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSkgJT4lCiAgICAgICAgICAgICAgIHNlbGVjdCguLC1DRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSkgJT4lCiAgICBtdXRhdGUoZWNpZ19ldmVyID0gY2FzZV93aGVuKGVjaWdfc3VtX2V2ZXIgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWNpZ19zdW1fZXZlciA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgZWNpZ19jdXJyZW50ID0gY2FzZV93aGVuKGVjaWdfc3VtX2N1cnJlbnQgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWNpZ19zdW1fY3VycmVudCA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgbm9uX2VjaWdfZXZlciA9IGNhc2Vfd2hlbihub25fZWNpZ19zdW1fZXZlciA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub25fZWNpZ19zdW1fZXZlciA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgbm9uX2VjaWdfY3VycmVudCA9IGNhc2Vfd2hlbihub25fZWNpZ19zdW1fY3VycmVudCA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub25fZWNpZ19zdW1fY3VycmVudCA9PTAgfiBGQUxTRSkpICU+JQogICAgZ3JvdXBfYnkoeWVhcikgJT4lCiAgICBzdW1tYXJpc2UoZWNpZ19ldmVyX3llYXI9KHN1bShlY2lnX2V2ZXIsIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICAgIHN1bSghaXMubmEoZWNpZ19ldmVyKSksCiAgICAgICAgICAgICAgZWNpZ19jdXJyZW50X3llYXI9KHN1bShlY2lnX2N1cnJlbnQsIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICAgIHN1bSghaXMubmEoZWNpZ19jdXJyZW50KSksCiAgICAgICAgICAgICAgbm9uX2VjaWdfZXZlcl95ZWFyPShzdW0obm9uX2VjaWdfZXZlciwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgICAgc3VtKCFpcy5uYShub25fZWNpZ19ldmVyKSksCiAgICAgICAgICAgICAgbm9uX2VjaWdfY3VycmVudF95ZWFyPShzdW0obm9uX2VjaWdfY3VycmVudCwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgICAgc3VtKCFpcy5uYShub25fZWNpZ19jdXJyZW50KSkpICU+JQogICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAteWVhciwgbmFtZXNfdG8gPSAiQ2F0ZWdvcnkiLCB2YWx1ZXNfdG8gPSAiUGVyY2VudGFnZSBvZiBzdHVkZW50cyIpICU+JQogICAgbXV0YXRlKFVzZXIgPSBjYXNlX3doZW4oQ2F0ZWdvcnkgPT0iZWNpZ19ldmVyX3llYXIiIH4gIkV2ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBDYXRlZ29yeSA9PSJub25fZWNpZ19ldmVyX3llYXIiIH4gIkV2ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBDYXRlZ29yeSA9PSJlY2lnX2N1cnJlbnRfeWVhciIgfiAiQ3VycmVudCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIENhdGVnb3J5ID09Im5vbl9lY2lnX2N1cnJlbnRfeWVhciIgfiAiQ3VycmVudCIpKSAlPiUKICAgIG11dGF0ZShQcm9kdWN0ID0gY2FzZV93aGVuKENhdGVnb3J5ID09ImVjaWdfZXZlcl95ZWFyIiB+ICJFLWNpZ2FyZXR0ZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBDYXRlZ29yeSA9PSJub25fZWNpZ19ldmVyX3llYXIiIH4gIk90aGVyIHByb2R1Y3RzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2F0ZWdvcnkgPT0iZWNpZ19jdXJyZW50X3llYXIiIH4gIkUtY2lnYXJldHRlcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIENhdGVnb3J5ID09Im5vbl9lY2lnX2N1cnJlbnRfeWVhciIgfiAiT3RoZXIgcHJvZHVjdHMiKSkgJT4lCiAgICBmaWx0ZXIoVXNlcj09IkV2ZXIiKSAlPiUKICAgIGdncGxvdChhZXMoeD15ZWFyLHk9YFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgLCBjb2xvcj1Qcm9kdWN0KSkgKwogICAgZ2VvbV9saW5lKGxpbmV0eXBlPTEpICsgIyBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIiwgY29sb3I9ImJsYWNrIikgKwogIGdlb21fcG9pbnQoc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMTAsIDYwLCBieSA9IDEwKSwgbGltaXRzID0gYygxMCw2MCkpICsKICAgIHRoZW1lX21pbmltYWwoKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogICAgbGFicyh0aXRsZSA9ICJIb3cgZG9lcyBlLWNpZ2FyZXR0ZSBldmVyIHVzZSBjb21wYXJlIHRvIGV2ZXIgdXNlIG9mIG90aGVyIHByb2R1Y3RzIG92ZXIgdGhlIHllYXJzPyIsCiAgICAgICAgIHN1YnRpdGxlID0gIkUtY2lnYXJldHRlIGFuZCBub24tZS1jaWdhcmV0dGUgdXNlIiwKICAgICAgICAgeSA9ICIlIG9mIHN0dWRlbnRzIikKCnBsb3Q3CmBgYAoKYGBge3J9CnBsb3Q4IDwtIG55dHNfZGF0YSAlPiUKICAgIG11dGF0ZShlY2lnX3N1bV9ldmVyID0gc2VsZWN0KC4sIEVFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpLAogICAgICAgICAgIGVjaWdfc3VtX2N1cnJlbnQgPSBzZWxlY3QoLiwgQ0VMQ0lHVCkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSksCiAgICAgICAgICAgbm9uX2VjaWdfc3VtX2V2ZXIgPSBzZWxlY3QoLiwgc3RhcnRzX3dpdGgoIkUiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSkgJT4lCiAgICAgICAgICAgICAgIHNlbGVjdCguLC1FRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICBub25fZWNpZ19zdW1fY3VycmVudCA9IHNlbGVjdCguLCBzdGFydHNfd2l0aCgiQyIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSAlPiUKICAgICAgICAgICAgICAgc2VsZWN0KC4sLUNFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpKSAlPiUKICAgIG11dGF0ZShlY2lnX2V2ZXIgPSBjYXNlX3doZW4oZWNpZ19zdW1fZXZlciA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlY2lnX3N1bV9ldmVyID09MCB+IEZBTFNFKSwKICAgICAgICAgICBlY2lnX2N1cnJlbnQgPSBjYXNlX3doZW4oZWNpZ19zdW1fY3VycmVudCA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlY2lnX3N1bV9jdXJyZW50ID09MCB+IEZBTFNFKSwKICAgICAgICAgICBub25fZWNpZ19ldmVyID0gY2FzZV93aGVuKG5vbl9lY2lnX3N1bV9ldmVyID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbl9lY2lnX3N1bV9ldmVyID09MCB+IEZBTFNFKSwKICAgICAgICAgICBub25fZWNpZ19jdXJyZW50ID0gY2FzZV93aGVuKG5vbl9lY2lnX3N1bV9jdXJyZW50ID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbl9lY2lnX3N1bV9jdXJyZW50ID09MCB+IEZBTFNFKSkgJT4lCiAgICBncm91cF9ieSh5ZWFyKSAlPiUKICAgIHN1bW1hcmlzZShlY2lnX2V2ZXJfeWVhcj0oc3VtKGVjaWdfZXZlciwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgICAgc3VtKCFpcy5uYShlY2lnX2V2ZXIpKSwKICAgICAgICAgICAgICBlY2lnX2N1cnJlbnRfeWVhcj0oc3VtKGVjaWdfY3VycmVudCwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgICAgc3VtKCFpcy5uYShlY2lnX2N1cnJlbnQpKSwKICAgICAgICAgICAgICBub25fZWNpZ19ldmVyX3llYXI9KHN1bShub25fZWNpZ19ldmVyLCBuYS5ybSA9IFRSVUUpKjEwMCkvCiAgICAgICAgICAgICAgICBzdW0oIWlzLm5hKG5vbl9lY2lnX2V2ZXIpKSwKICAgICAgICAgICAgICBub25fZWNpZ19jdXJyZW50X3llYXI9KHN1bShub25fZWNpZ19jdXJyZW50LCBuYS5ybSA9IFRSVUUpKjEwMCkvCiAgICAgICAgICAgICAgICBzdW0oIWlzLm5hKG5vbl9lY2lnX2N1cnJlbnQpKSkgJT4lCiAgICBwaXZvdF9sb25nZXIoY29scyA9IC15ZWFyLCBuYW1lc190byA9ICJDYXRlZ29yeSIsIHZhbHVlc190byA9ICJQZXJjZW50YWdlIG9mIHN0dWRlbnRzIikgJT4lCiAgICAjIGdhdGhlcihrZXk9Q2F0ZWdvcnksCiAgICAjICAgICAgICB2YWx1ZT1gUGVyY2VudGFnZSBvZiBzdHVkZW50c2AsCiAgICAjICAgICAgICAteWVhcikgJT4lCiAgICBtdXRhdGUoVXNlciA9IGNhc2Vfd2hlbihDYXRlZ29yeSA9PSJlY2lnX2V2ZXJfeWVhciIgfiAiRXZlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIENhdGVnb3J5ID09Im5vbl9lY2lnX2V2ZXJfeWVhciIgfiAiRXZlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIENhdGVnb3J5ID09ImVjaWdfY3VycmVudF95ZWFyIiB+ICJDdXJyZW50IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2F0ZWdvcnkgPT0ibm9uX2VjaWdfY3VycmVudF95ZWFyIiB+ICJDdXJyZW50IikpICU+JQogICAgbXV0YXRlKFByb2R1Y3QgPSBjYXNlX3doZW4oQ2F0ZWdvcnkgPT0iZWNpZ19ldmVyX3llYXIiIH4gIkUtY2lnYXJldHRlcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIENhdGVnb3J5ID09Im5vbl9lY2lnX2V2ZXJfeWVhciIgfiAiT3RoZXIgcHJvZHVjdHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBDYXRlZ29yeSA9PSJlY2lnX2N1cnJlbnRfeWVhciIgfiAiRS1jaWdhcmV0dGVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2F0ZWdvcnkgPT0ibm9uX2VjaWdfY3VycmVudF95ZWFyIiB+ICJPdGhlciBwcm9kdWN0cyIpKSAlPiUKICAgIGdncGxvdChhZXMoeD15ZWFyLHk9YFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgLCBjb2xvcj1Qcm9kdWN0LCBsaW5ldHlwZT1Vc2VyKSkgKwogICAgZ2VvbV9saW5lKCkgKwogIGdlb21fcG9pbnQoc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIHNjYWxlX2xpbmV0eXBlX21hbnVhbCh2YWx1ZXMgPSBjKDIsMSkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDYwLCBieSA9IDEwKSwgbGltaXRzID0gYygwLDYwKSkgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpKSArCiAgICBsYWJzKHRpdGxlID0gIkhvdyBkb2VzIGUtY2lnYXJldHRlIHVzZSBjb21wYXJlIHRvIHVzZSBvZiBvdGhlciBwcm9kdWN0cyBvdmVyIHRoZSB5ZWFycz8iLAogICAgICAgICBzdWJ0aXRsZSA9ICJFLWNpZ2FyZXR0ZSBhbmQgbm9uLWUtY2lnYXJldHRlIHVzZSIsCiAgICAgICAgIHkgPSAiJSBvZiBzdHVkZW50cyIpCgpwbG90OApgYGAKCiMjIyBVbndlaWdodGVkIFNhbXBsZQoKYGBge3IsIGZpZy5oZWlnaHQ9MTB9CnBsb3RBX3V3IDwtIHBsb3QxICsKICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgICBsYWJzKHRpdGxlID0gIk5pY290aW5lIHByb2R1Y3QgdXNlcnMgbW9yZSBwcmV2YWxlbnQgYWZ0ZXIgMjAxNyIsCiAgICAgICAgIHN1YnRpdGxlID0gTlVMTCwKICAgICAgICAgeSA9ICIlIG9mIHN0dWRlbnRzIikKCnBsb3RCX3V3IDwtIHBsb3Q3ICsgCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgbGFicyh0aXRsZSA9ICIlIEV2ZXIgdHJ5aW5nIGUtY2lnYXJldHRlcyBpbmNyZWFzZXMgJlxuJSBldmVyIHRyeWluZyBvdGhlciBwcm9kdWN0cyBkZWNyZWFzZXMiLAogICAgICAgICBzdWJ0aXRsZSA9IE5VTEwsCiAgICAgICAgIHkgPSAiJSBvZiBzdHVkZW50cyIpCgpwbG90Q191dyA8LSBwbG90OCArIAogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsKICAgIGxhYnModGl0bGUgPSAiJSBVc2luZyBlLWNpZ2FyZXR0ZXMgaW5jcmVhc2VzICZcbiUgdXNpbmcgT3RoZXIgcHJvZHVjdHMgZGVjcmVhc2VzIiwKICAgICAgICAgc3VidGl0bGUgPSBOVUxMLAogICAgICAgICB5ID0gIiUgb2Ygc3R1ZGVudHMiKQoKdGl0bGVfdXcgPC0gZ2dkcmF3KCkgKyAKICBkcmF3X2xhYmVsKAogICAgIkhhdmUgdmFwaW5nIHJhdGVzIHBvc3NpYmx5IGluZmx1ZW5jZWQgdG9iYWNjby9uaWNvdGluZSB1c2U/IiwKICAgIGZvbnRmYWNlID0gJ2JvbGQnLAogICAgc2l6ZT0xNCwKICAgIHggPSAwLAogICAgaGp1c3QgPSAwCiAgKSArCiAgdGhlbWUoCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLCAwLCAwLCAwKQogICkKCnBsb3RzQV91dyA8LSBwbG90X2dyaWQocGxvdEFfdXcsCiAgICAgICAgICAgICAgICAgICAgIHJlbF93aWR0aHMgPSBjKDEsMSkpCnBsb3RzQkNfdXcgPC0gcGxvdF9ncmlkKHBsb3RCX3V3LAogICAgICAgICAgICAgICAgICAgICAgICBwbG90Q191dywKICAgICAgICAgICAgICAgICAgICAgICAgcmVsX3dpZHRocyA9IGMoMSwxKSkKCmxlZ2VuZF91dyA8LSBnZXRfbGVnZW5kKHBsb3RCX3V3ICsKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQuZGlyZWN0aW9uID0gImhvcml6b250YWwiKSkKCmZpZ3VyZV91dyA8LSBwbG90X2dyaWQodGl0bGVfdXcsCiAgICAgICAgICAgICAgICAgICAgICAgcGxvdHNBX3V3LAogICAgICAgICAgICAgICAgICAgICAgIHBsb3RzQkNfdXcsCiAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kX3V3LAogICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAxLAogICAgICAgICAgICAgICAgICAgICAgIHJlbF9oZWlnaHRzID0gYygwLjEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDAuMSksCiAgICAgICAgICAgICAgICAgICAgICAgc2NhbGUgPSAxLjApCgpmaWd1cmVfdXcKYGBgCgojIyMgV2VpZ2h0ZWQgU2FtcGxlCgpgYGB7cn0KcGxvdEFfdyA8LSBueXRzX2RhdGEgJT4lCiAgICBtdXRhdGUodG9iYWNjb19zdW1fZXZlciA9IHNlbGVjdCguLCBzdGFydHNfd2l0aCgiRSIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICB0b2JhY2NvX3N1bV9jdXJyZW50ID0gc2VsZWN0KC4sIHN0YXJ0c193aXRoKCJDIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpKSAlPiUKICAgIG11dGF0ZSh0b2JhY2NvX2V2ZXIgPSBjYXNlX3doZW4odG9iYWNjb19zdW1fZXZlciA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b2JhY2NvX3N1bV9ldmVyID09MCB+IEZBTFNFKSwKICAgICAgICAgICB0b2JhY2NvX2N1cnJlbnQgPSBjYXNlX3doZW4odG9iYWNjb19zdW1fY3VycmVudCA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b2JhY2NvX3N1bV9jdXJyZW50ID09MCB+IEZBTFNFKSkgJT4lCiAgYXNfc3VydmV5X2Rlc2lnbihzdHJhdGEgPSBzdHJhdHVtLCBpZHMgPSBwc3UsIHdlaWdodCAgPSBmaW53Z3QsIG5lc3Q9VFJVRSkgJT4lCiAgICBncm91cF9ieSh5ZWFyKSAlPiUKICBzdW1tYXJpc2UodG9iYWNjb19ldmVyX3llYXIgPSBzdXJ2ZXlfbWVhbih0b2JhY2NvX2V2ZXIsIHZhcnR5cGUgPSAiY2kiLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICAgdG9iYWNjb19jdXJyZW50X3llYXIgPSBzdXJ2ZXlfbWVhbih0b2JhY2NvX2N1cnJlbnQsIHZhcnR5cGUgPSAiY2kiLCBuYS5ybT1UUlVFKSkgICU+JQogIG11dGF0ZV9hdCh2YXJzKC15ZWFyKSwgIioiLCAxMDApICU+JQogICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAteWVhciwgbmFtZXNfdG8gPSAiVHlwZSIsIHZhbHVlc190byA9ICJQZXJjZW50YWdlIG9mIHN0dWRlbnRzIikgJT4lCiAgICAjIGdhdGhlcihrZXk9VHlwZSwKICAgICMgICAgICAgIHZhbHVlPWBQZXJjZW50YWdlIG9mIHN0dWRlbnRzYCwKICAgICMgICAgICAgIC15ZWFyKSAlPiUKICBtdXRhdGUoRXN0aW1hdGUgPSBjYXNlX3doZW4oZ3JlcGwoIl9sb3ciLCBUeXBlKSB+ICJMb3dlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JlcGwoIl91cHAiLCBUeXBlKSB+ICJVcHBlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICJNZWFuIiksCiAgICAgICAgIFVzZXIgPSBjYXNlX3doZW4oZ3JlcGwoImV2ZXIiLCBUeXBlKSB+ICJFdmVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBncmVwbCgiY3VycmVudCIsIFR5cGUpIH4gIkN1cnJlbnQiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiTWVhbiIpKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1UeXBlKSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gRXN0aW1hdGUsIAogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gYFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgKSAlPiUKICAjc3ByZWFkKEVzdGltYXRlLCBgUGVyY2VudGFnZSBvZiBzdHVkZW50c2ApICU+JQogIGdncGxvdChhZXMoeD15ZWFyLHk9TWVhbikpICsKICBnZW9tX2xpbmUoYWVzKGxpbmV0eXBlPVVzZXIpKSArCiAgZ2VvbV9saW5lcmFuZ2UoYWVzKHltaW4gPSBMb3dlciwgeW1heCA9IFVwcGVyKSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIHNjYWxlX2xpbmV0eXBlX21hbnVhbCh2YWx1ZXMgPSBjKDIsMSkpICsKICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCw3MCxieT0xMCksCiAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2VxKDAsNzAsYnk9MTApLAogICAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMCw3MCkpICsKICAgIHRoZW1lX21pbmltYWwoKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICAgIGxhYnModGl0bGUgPSAiTmljb3RpbmUgcHJvZHVjdCB1c2VycyBtb3JlIHByZXZhbGVudCBhZnRlciAyMDE3IiwKICAgICAgICAgeSA9ICIlIG9mIHN0dWRlbnRzIikKCnBsb3RCX3cgPC0gbnl0c19kYXRhICU+JQogICAgbXV0YXRlKGVjaWdfc3VtX2V2ZXIgPSBzZWxlY3QoLiwgRUVMQ0lHVCkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSksCiAgICAgICAgICAgZWNpZ19zdW1fY3VycmVudCA9IHNlbGVjdCguLCBDRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICBub25fZWNpZ19zdW1fZXZlciA9IHNlbGVjdCguLCBzdGFydHNfd2l0aCgiRSIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSAlPiUKICAgICAgICAgICAgICAgc2VsZWN0KC4sLUVFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpLAogICAgICAgICAgIG5vbl9lY2lnX3N1bV9jdXJyZW50ID0gc2VsZWN0KC4sIHN0YXJ0c193aXRoKCJDIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpICU+JQogICAgICAgICAgICAgICBzZWxlY3QoLiwtQ0VMQ0lHVCkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSkpICU+JQogICAgbXV0YXRlKGVjaWdfZXZlciA9IGNhc2Vfd2hlbihlY2lnX3N1bV9ldmVyID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVjaWdfc3VtX2V2ZXIgPT0wIH4gRkFMU0UpLAogICAgICAgICAgIGVjaWdfY3VycmVudCA9IGNhc2Vfd2hlbihlY2lnX3N1bV9jdXJyZW50ID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVjaWdfc3VtX2N1cnJlbnQgPT0wIH4gRkFMU0UpLAogICAgICAgICAgIG5vbl9lY2lnX2V2ZXIgPSBjYXNlX3doZW4obm9uX2VjaWdfc3VtX2V2ZXIgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9uX2VjaWdfc3VtX2V2ZXIgPT0wIH4gRkFMU0UpLAogICAgICAgICAgIG5vbl9lY2lnX2N1cnJlbnQgPSBjYXNlX3doZW4obm9uX2VjaWdfc3VtX2N1cnJlbnQgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9uX2VjaWdfc3VtX2N1cnJlbnQgPT0wIH4gRkFMU0UpKSAlPiUKICBhc19zdXJ2ZXlfZGVzaWduKHN0cmF0YSA9IHN0cmF0dW0sIGlkcyA9IHBzdSwgd2VpZ2h0ICA9IGZpbndndCwgbmVzdD1UUlVFKSAlPiUKICAgIGdyb3VwX2J5KHllYXIpICU+JQogICAgc3VtbWFyaXNlKGVjaWdfZXZlcl95ZWFyID0gc3VydmV5X21lYW4oZWNpZ19ldmVyLCB2YXJ0eXBlID0gImNpIiwgbmEucm09VFJVRSksCiAgICAgICAgICAgIGVjaWdfY3VycmVudF95ZWFyID0gc3VydmV5X21lYW4oZWNpZ19jdXJyZW50LCB2YXJ0eXBlID0gImNpIiwgbmEucm09VFJVRSksCiAgICAgICAgICAgIG5vbl9lY2lnX2V2ZXJfeWVhciA9IHN1cnZleV9tZWFuKG5vbl9lY2lnX2V2ZXIsIHZhcnR5cGUgPSAiY2kiLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICAgbm9uX2VjaWdfY3VycmVudF95ZWFyID0gc3VydmV5X21lYW4obm9uX2VjaWdfY3VycmVudCwgdmFydHlwZSA9ICJjaSIsIG5hLnJtPVRSVUUpKSAlPiUKICBtdXRhdGVfYXQodmFycygteWVhciksICIqIiwgMTAwKSAlPiUKICBkcGx5cjo6c2VsZWN0KHllYXIsCiAgICAgICAgICAgICAgICBlY2lnX2V2ZXJfeWVhciwKICAgICAgICAgICAgICAgIGVjaWdfY3VycmVudF95ZWFyLAogICAgICAgICAgICAgICAgbm9uX2VjaWdfZXZlcl95ZWFyLAogICAgICAgICAgICAgICAgbm9uX2VjaWdfY3VycmVudF95ZWFyLAogICAgICAgICAgICAgICAgY29udGFpbnMoImxvdyIpLAogICAgICAgICAgICAgICAgY29udGFpbnMoInVwcCIpKSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IC15ZWFyLCBuYW1lc190byA9ICJDYXRlZ29yeSIsIHZhbHVlc190byA9ICJQZXJjZW50YWdlIG9mIHN0dWRlbnRzIikgJT4lCiAgICAjIGdhdGhlcihrZXk9Q2F0ZWdvcnksCiAgICAjICAgICAgICB2YWx1ZT1gUGVyY2VudGFnZSBvZiBzdHVkZW50c2AsCiAgICAjICAgICAgICAteWVhcikgICU+JQogIG11dGF0ZShFc3RpbWF0ZSA9IGNhc2Vfd2hlbihncmVwbCgiX2xvdyIsIENhdGVnb3J5KSB+ICJMb3dlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JlcGwoIl91cHAiLCBDYXRlZ29yeSkgfiAiVXBwZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiTWVhbiIpLAogICAgICAgICBVc2VyID0gY2FzZV93aGVuKGdyZXBsKCJjdXJyZW50IiwgQ2F0ZWdvcnkpIH4gIkN1cnJlbnQiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiRXZlciIsKSwKICAgICAgICAgUHJvZHVjdCA9IGNhc2Vfd2hlbihncmVwbCgibm9uX2VjaWciLCBDYXRlZ29yeSkgfiAiT3RoZXIgcHJvZHVjdHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiRS1jaWdhcmV0dGVzIikpICU+JQogIGRwbHlyOjpzZWxlY3QoLUNhdGVnb3J5KSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gRXN0aW1hdGUsIAogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gYFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgKSAlPiUKICAjc3ByZWFkKEVzdGltYXRlLCBgUGVyY2VudGFnZSBvZiBzdHVkZW50c2ApICU+JQogIGZpbHRlcihVc2VyPT0iRXZlciIpICU+JQogIGRwbHlyOjpyZW5hbWUoIkxvd2VyX3RlbXAiID0gVXBwZXIsCiAgICAgICAgICAgICAgICAiVXBwZXJfdGVtcCIgPSBMb3dlcikgJT4lCiAgZHBseXI6OnJlbmFtZSgiTG93ZXIiPUxvd2VyX3RlbXAsCiAgICAgICAgICAgICAgICAiVXBwZXIiPVVwcGVyX3RlbXApICU+JQogICAgZ2dwbG90KGFlcyh4PXllYXIseT1NZWFuLCBjb2xvcj1Qcm9kdWN0KSkgKwogIGdlb21fbGluZShsaW5ldHlwZT0xKSArCiAgZ2VvbV9saW5lcmFuZ2UoYWVzKHltaW4gPSBMb3dlciwgeW1heCA9IFVwcGVyKSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMTAsIDYwLCBieSA9IDEwKSwgbGltaXRzID0gYygxMCw2MCkpICsKICAgIHRoZW1lX21pbmltYWwoKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICAgIGxhYnModGl0bGUgPSAiJSBldmVyIHRyeWluZyBlLWNpZ2FyZXR0ZXMgaW5jcmVhc2VzICZcbiUgZXZlciB0cnlpbmcgb3RoZXIgcHJvZHVjdHMgZGVjcmVhc2VzIiwKICAgICAgICAgeSA9ICIlIG9mIHN0dWRlbnRzIikKCiMjIyMgdGhlIHdyYW5nbGluZyBsb29rcyB0aGUgc2FtZSBhcyB0aGUgYWJvdmUgcGxvdC4uLgpwbG90Q193IDwtIG55dHNfZGF0YSAlPiUKICAgIG11dGF0ZShlY2lnX3N1bV9ldmVyID0gc2VsZWN0KC4sIEVFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpLAogICAgICAgICAgIGVjaWdfc3VtX2N1cnJlbnQgPSBzZWxlY3QoLiwgQ0VMQ0lHVCkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSksCiAgICAgICAgICAgbm9uX2VjaWdfc3VtX2V2ZXIgPSBzZWxlY3QoLiwgc3RhcnRzX3dpdGgoIkUiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSkgJT4lCiAgICAgICAgICAgICAgIHNlbGVjdCguLC1FRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICBub25fZWNpZ19zdW1fY3VycmVudCA9IHNlbGVjdCguLCBzdGFydHNfd2l0aCgiQyIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSAlPiUKICAgICAgICAgICAgICAgc2VsZWN0KC4sLUNFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpKSAlPiUKICAgIG11dGF0ZShlY2lnX2V2ZXIgPSBjYXNlX3doZW4oZWNpZ19zdW1fZXZlciA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlY2lnX3N1bV9ldmVyID09MCB+IEZBTFNFKSwKICAgICAgICAgICBlY2lnX2N1cnJlbnQgPSBjYXNlX3doZW4oZWNpZ19zdW1fY3VycmVudCA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlY2lnX3N1bV9jdXJyZW50ID09MCB+IEZBTFNFKSwKICAgICAgICAgICBub25fZWNpZ19ldmVyID0gY2FzZV93aGVuKG5vbl9lY2lnX3N1bV9ldmVyID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbl9lY2lnX3N1bV9ldmVyID09MCB+IEZBTFNFKSwKICAgICAgICAgICBub25fZWNpZ19jdXJyZW50ID0gY2FzZV93aGVuKG5vbl9lY2lnX3N1bV9jdXJyZW50ID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbl9lY2lnX3N1bV9jdXJyZW50ID09MCB+IEZBTFNFKSkgJT4lCiAgYXNfc3VydmV5X2Rlc2lnbihzdHJhdGEgPSBzdHJhdHVtLCBpZHMgPSBwc3UsIHdlaWdodCAgPSBmaW53Z3QsIG5lc3Q9VFJVRSkgJT4lCiAgICBncm91cF9ieSh5ZWFyKSAlPiUKICBzdW1tYXJpc2UoZWNpZ19ldmVyX3llYXIgPSBzdXJ2ZXlfbWVhbihlY2lnX2V2ZXIsIHZhcnR5cGUgPSAiY2kiLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICAgZWNpZ19jdXJyZW50X3llYXIgPSBzdXJ2ZXlfbWVhbihlY2lnX2N1cnJlbnQsIHZhcnR5cGUgPSAiY2kiLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICAgbm9uX2VjaWdfZXZlcl95ZWFyID0gc3VydmV5X21lYW4obm9uX2VjaWdfZXZlciwgdmFydHlwZSA9ICJjaSIsIG5hLnJtPVRSVUUpLAogICAgICAgICAgICBub25fZWNpZ19jdXJyZW50X3llYXIgPSBzdXJ2ZXlfbWVhbihub25fZWNpZ19jdXJyZW50LCB2YXJ0eXBlID0gImNpIiwgbmEucm09VFJVRSkpICU+JQogIG11dGF0ZV9hdCh2YXJzKC15ZWFyKSwgIioiLCAxMDApICU+JQogIGRwbHlyOjpzZWxlY3QoeWVhciwKICAgICAgICAgICAgICAgIGVjaWdfZXZlcl95ZWFyLAogICAgICAgICAgICAgICAgZWNpZ19jdXJyZW50X3llYXIsCiAgICAgICAgICAgICAgICBub25fZWNpZ19ldmVyX3llYXIsCiAgICAgICAgICAgICAgICBub25fZWNpZ19jdXJyZW50X3llYXIsCiAgICAgICAgICAgICAgICBjb250YWlucygibG93IiksCiAgICAgICAgICAgICAgICBjb250YWlucygidXBwIikpICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gLXllYXIsIG5hbWVzX3RvID0gIkNhdGVnb3J5IiwgdmFsdWVzX3RvID0gIlBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHMiKSAlPiUKICAgICMgZ2F0aGVyKGtleT1DYXRlZ29yeSwKICAgICMgICAgICAgIHZhbHVlPWBQZXJjZW50YWdlIG9mIHN0dWRlbnRzYCwKICAgICMgICAgICAgIC15ZWFyKSAlPiUKICAgIG11dGF0ZShFc3RpbWF0ZSA9IGNhc2Vfd2hlbihncmVwbCgiX2xvdyIsIENhdGVnb3J5KSB+ICJMb3dlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JlcGwoIl91cHAiLCBDYXRlZ29yeSkgfiAiVXBwZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiTWVhbiIpLAogICAgICAgICBVc2VyID0gY2FzZV93aGVuKGdyZXBsKCJldmVyIiwgQ2F0ZWdvcnkpIH4gIkV2ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGdyZXBsKCJjdXJyZW50IiwgQ2F0ZWdvcnkpIH4gIkN1cnJlbnQiKSwKICAgICAgICAgUHJvZHVjdCA9IGNhc2Vfd2hlbihncmVwbCgibm9uX2VjaWciLCBDYXRlZ29yeSkgfiAiT3RoZXIgcHJvZHVjdHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiRS1jaWdhcmV0dGVzIikpICU+JQogIGRwbHlyOjpzZWxlY3QoLUNhdGVnb3J5KSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gRXN0aW1hdGUsIAogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gYFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgKSAlPiUKICAjc3ByZWFkKEVzdGltYXRlLCBgUGVyY2VudGFnZSBvZiBzdHVkZW50c2ApICU+JQogICAgZ2dwbG90KGFlcyh4PXllYXIseT1NZWFuLCBjb2xvcj1Qcm9kdWN0KSkgKwogIGdlb21fbGluZShhZXMobGluZXR5cGU9VXNlcikpICsKICBnZW9tX2xpbmVyYW5nZShhZXMoeW1pbiA9IExvd2VyLCB5bWF4ID0gVXBwZXIpLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgc2NhbGVfbGluZXR5cGVfbWFudWFsKHZhbHVlcyA9IGMoMiwxKSkgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgNjAsIGJ5ID0gMTApLCBsaW1pdHMgPSBjKDAsNjApKSArCiAgICB0aGVtZV9taW5pbWFsKCkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpKSArCiAgICBsYWJzKHRpdGxlID0gIiUgVXNpbmcgZS1jaWdhcmV0dGVzIGluY3JlYXNlcyAmXG4lIHVzaW5nIE90aGVyIHByb2R1Y3RzIGRlY3JlYXNlcyIsCiAgICAgICAgIHkgPSAiJSBvZiBzdHVkZW50cyIpCgp0aXRsZV93IDwtIGdnZHJhdygpICsgCiAgZHJhd19sYWJlbCgKICAgIGV4cHJlc3Npb24oIkhhdmUgdmFwaW5nIHJhdGVzIHBvc3NpYmx5IGluZmx1ZW5jZWQgdG9iYWNjby9uaWNvdGluZSB1c2U/IiksCiAgICBmb250ZmFjZSA9ICdib2xkJywKICAgIHNpemU9MTQsCiAgICB4ID0gMCwKICAgIGhqdXN0ID0gMAogICkgKwogIHRoZW1lKAogICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4oMCwgMCwgMCwgMCkKICApCgpwbG90c0FfdyA8LSBwbG90X2dyaWQocGxvdEFfdywKICAgICAgICAgICAgICAgICAgICAgcmVsX3dpZHRocyA9IGMoMSksCiAgICAgICAgICAgICAgICAgICAgIGFsaWduID0gInYiLAogICAgICAgICAgICAgICAgICAgICBheGlzID0gImJ0IikKcGxvdHNCQ193IDwtIHBsb3RfZ3JpZChwbG90Ql93LAogICAgICAgICAgICAgICAgICAgICBwbG90Q193LAogICAgICAgICAgICAgICAgICAgICByZWxfd2lkdGhzID0gYygxLDEpLAogICAgICAgICAgICAgICAgICAgICBhbGlnbiA9ICJ2IiwKICAgICAgICAgICAgICAgICAgICAgYXhpcyA9ICJidCIpCgpsZWdlbmRfdyA8LSBnZXRfbGVnZW5kKHBsb3RCX3cgKwogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC5kaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIpKQoKZmlndXJlX3cgPC0gcGxvdF9ncmlkKHRpdGxlX3csCiAgICAgICAgICAgICAgICAgICAgICBwbG90c0FfdywKICAgICAgICAgICAgICAgICAgICAgIHBsb3RzQkNfdywKICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZF93LAogICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDEsCiAgICAgICAgICAgICAgICAgICAgICByZWxfaGVpZ2h0cyA9IGMoMC4xLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAwLjEpLAogICAgICAgICAgICAgICAgICAgICAgc2NhbGUgPSAxLjApCgpmaWd1cmVfdwpgYGAKCiMjIyBIeXBvdGhldGhpY2FsIENvaG9ydAoKYGBge3J9CnBsb3RBX3dfOCA8LSBueXRzX2RhdGEgJT4lCiAgZmlsdGVyKChHcmFkZSA9PSAiOCIgJiB5ZWFyID09IDIwMTUpIHwKICAgICAgICAgKEdyYWRlID09ICI5IiAmIHllYXIgPT0gMjAxNikgfAogICAgICAgICAoR3JhZGUgPT0gIjEwIiAmIHllYXIgPT0gMjAxNykgfAogICAgICAgICAoR3JhZGUgPT0gIjExIiAmIHllYXIgPT0gMjAxOCkgfAogICAgICAgICAgKEdyYWRlID09ICIxMiIgJiB5ZWFyID09IDIwMTkpIAogICAgICAgICApICU+JQogICAgbXV0YXRlKHRvYmFjY29fc3VtX2V2ZXIgPSBzZWxlY3QoLiwgc3RhcnRzX3dpdGgoIkUiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSksCiAgICAgICAgICAgdG9iYWNjb19zdW1fY3VycmVudCA9IHNlbGVjdCguLCBzdGFydHNfd2l0aCgiQyIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSkgJT4lCiAgICBtdXRhdGUodG9iYWNjb19ldmVyID0gY2FzZV93aGVuKHRvYmFjY29fc3VtX2V2ZXIgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9iYWNjb19zdW1fZXZlciA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgdG9iYWNjb19jdXJyZW50ID0gY2FzZV93aGVuKHRvYmFjY29fc3VtX2N1cnJlbnQgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9iYWNjb19zdW1fY3VycmVudCA9PTAgfiBGQUxTRSkpICU+JQogIGFzX3N1cnZleV9kZXNpZ24oc3RyYXRhID0gc3RyYXR1bSwgaWRzID0gcHN1LCB3ZWlnaHQgID0gZmlud2d0KSAlPiUKICAgIGdyb3VwX2J5KHllYXIpICU+JQogIHN1bW1hcmlzZSh0b2JhY2NvX2V2ZXJfeWVhciA9IHN1cnZleV9tZWFuKHRvYmFjY29fZXZlciwgdmFydHlwZSA9ICJjaSIsIG5hLnJtPVRSVUUpLAogICAgICAgICAgICB0b2JhY2NvX2N1cnJlbnRfeWVhciA9IHN1cnZleV9tZWFuKHRvYmFjY29fY3VycmVudCwgdmFydHlwZSA9ICJjaSIsIG5hLnJtPVRSVUUpKSAgJT4lCiAgbXV0YXRlX2F0KHZhcnMoLXllYXIpLCAiKiIsIDEwMCkgJT4lCiAgICBwaXZvdF9sb25nZXIoY29scyA9IC15ZWFyLCBuYW1lc190byA9ICJUeXBlIiwgdmFsdWVzX3RvID0gIlBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHMiKSU+JQogICAgIyBnYXRoZXIoa2V5PVR5cGUsCiAgICAjICAgICAgICB2YWx1ZT1gUGVyY2VudGFnZSBvZiBzdHVkZW50c2AsCiAgICAjICAgICAgICAteWVhcikgJT4lCiAgbXV0YXRlKEVzdGltYXRlID0gY2FzZV93aGVuKGdyZXBsKCJfbG93IiwgVHlwZSkgfiAiTG93ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGdyZXBsKCJfdXBwIiwgVHlwZSkgfiAiVXBwZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiTWVhbiIpLAogICAgICAgICBVc2VyID0gY2FzZV93aGVuKGdyZXBsKCJldmVyIiwgVHlwZSkgfiAiRXZlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JlcGwoImN1cnJlbnQiLCBUeXBlKSB+ICJDdXJyZW50IiwKICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIk1lYW4iKSkgJT4lCiAgZHBseXI6OnNlbGVjdCgtVHlwZSkgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IEVzdGltYXRlLCAKICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IGBQZXJjZW50YWdlIG9mIHN0dWRlbnRzYCkgJT4lCiAgI3NwcmVhZChFc3RpbWF0ZSwgYFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgKSAlPiUKICBnZ3Bsb3QoYWVzKHg9eWVhcix5PU1lYW4pKSArCiAgZ2VvbV9saW5lKGFlcyhsaW5ldHlwZT1Vc2VyKSkgKwogIGdlb21fbGluZXJhbmdlKGFlcyh5bWluID0gTG93ZXIsIHltYXggPSBVcHBlcikpICsgCiAgc2NhbGVfbGluZXR5cGVfbWFudWFsKHZhbHVlcyA9IGMoMiwxKSkgKwogICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDcwLGJ5PTEwKSwKICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzZXEoMCw3MCxieT0xMCksCiAgICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygwLDcwKSkgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogICAgbGFicyh0aXRsZSA9ICJOaWNvdGluZSBwcm9kdWN0IHVzZXJzIGJlY29taW5nIGluY3JlYXNpbmdseSBwcmV2YWxlbnQiLAogICAgICAgICB5ID0gIiUgb2Ygc3R1ZGVudHMiKQoKcGxvdEJfd184IDwtIG55dHNfZGF0YSAlPiUKICBmaWx0ZXIoKEdyYWRlID09ICI4IiAmIHllYXIgPT0gMjAxNSkgfAogICAgICAgICAoR3JhZGUgPT0gIjkiICYgeWVhciA9PSAyMDE2KSB8CiAgICAgICAgIChHcmFkZSA9PSAiMTAiICYgeWVhciA9PSAyMDE3KSB8CiAgICAgICAgIChHcmFkZSA9PSAiMTEiICYgeWVhciA9PSAyMDE4KSB8CiAgICAgICAgICAoR3JhZGUgPT0gIjEyIiAmIHllYXIgPT0gMjAxOSkgCiAgICAgICAgICkgJT4lCiAgICBtdXRhdGUoZWNpZ19zdW1fZXZlciA9IHNlbGVjdCguLCBFRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICBlY2lnX3N1bV9jdXJyZW50ID0gc2VsZWN0KC4sIENFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpLAogICAgICAgICAgIG5vbl9lY2lnX3N1bV9ldmVyID0gc2VsZWN0KC4sIHN0YXJ0c193aXRoKCJFIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpICU+JQogICAgICAgICAgICAgICBzZWxlY3QoLiwtRUVMQ0lHVCkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSksCiAgICAgICAgICAgbm9uX2VjaWdfc3VtX2N1cnJlbnQgPSBzZWxlY3QoLiwgc3RhcnRzX3dpdGgoIkMiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSkgJT4lCiAgICAgICAgICAgICAgIHNlbGVjdCguLC1DRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSkgJT4lCiAgICBtdXRhdGUoZWNpZ19ldmVyID0gY2FzZV93aGVuKGVjaWdfc3VtX2V2ZXIgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWNpZ19zdW1fZXZlciA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgZWNpZ19jdXJyZW50ID0gY2FzZV93aGVuKGVjaWdfc3VtX2N1cnJlbnQgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWNpZ19zdW1fY3VycmVudCA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgbm9uX2VjaWdfZXZlciA9IGNhc2Vfd2hlbihub25fZWNpZ19zdW1fZXZlciA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub25fZWNpZ19zdW1fZXZlciA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgbm9uX2VjaWdfY3VycmVudCA9IGNhc2Vfd2hlbihub25fZWNpZ19zdW1fY3VycmVudCA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub25fZWNpZ19zdW1fY3VycmVudCA9PTAgfiBGQUxTRSkpICU+JQogIGFzX3N1cnZleV9kZXNpZ24oc3RyYXRhID0gc3RyYXR1bSwgaWRzID0gcHN1LCB3ZWlnaHQgID0gZmlud2d0KSAlPiUKICAgIGdyb3VwX2J5KHllYXIpICU+JQogICAgc3VtbWFyaXNlKGVjaWdfZXZlcl95ZWFyID0gc3VydmV5X21lYW4oZWNpZ19ldmVyLCB2YXJ0eXBlID0gImNpIiwgbmEucm09VFJVRSksCiAgICAgICAgICAgIGVjaWdfY3VycmVudF95ZWFyID0gc3VydmV5X21lYW4oZWNpZ19jdXJyZW50LCB2YXJ0eXBlID0gImNpIiwgbmEucm09VFJVRSksCiAgICAgICAgICAgIG5vbl9lY2lnX2V2ZXJfeWVhciA9IHN1cnZleV9tZWFuKG5vbl9lY2lnX2V2ZXIsIHZhcnR5cGUgPSAiY2kiLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICAgbm9uX2VjaWdfY3VycmVudF95ZWFyID0gc3VydmV5X21lYW4obm9uX2VjaWdfY3VycmVudCwgdmFydHlwZSA9ICJjaSIsIG5hLnJtPVRSVUUpKSAlPiUKICBtdXRhdGVfYXQodmFycygteWVhciksICIqIiwgMTAwKSAlPiUKICBkcGx5cjo6c2VsZWN0KHllYXIsCiAgICAgICAgICAgICAgICBlY2lnX2V2ZXJfeWVhciwKICAgICAgICAgICAgICAgIGVjaWdfY3VycmVudF95ZWFyLAogICAgICAgICAgICAgICAgbm9uX2VjaWdfZXZlcl95ZWFyLAogICAgICAgICAgICAgICAgbm9uX2VjaWdfY3VycmVudF95ZWFyLAogICAgICAgICAgICAgICAgY29udGFpbnMoImxvdyIpLAogICAgICAgICAgICAgICAgY29udGFpbnMoInVwcCIpKSAlPiUKICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAteWVhciwgbmFtZXNfdG8gPSAiQ2F0ZWdvcnkiLCB2YWx1ZXNfdG8gPSAiUGVyY2VudGFnZSBvZiBzdHVkZW50cyIpJT4lCiAgICAjIGdhdGhlcihrZXk9Q2F0ZWdvcnksCiAgICAjICAgICAgICB2YWx1ZT1gUGVyY2VudGFnZSBvZiBzdHVkZW50c2AsCiAgICAjICAgICAgICAteWVhcikgICU+JQogIG11dGF0ZShFc3RpbWF0ZSA9IGNhc2Vfd2hlbihncmVwbCgiX2xvdyIsIENhdGVnb3J5KSB+ICJMb3dlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JlcGwoIl91cHAiLCBDYXRlZ29yeSkgfiAiVXBwZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiTWVhbiIpLAogICAgICAgICBVc2VyID0gY2FzZV93aGVuKGdyZXBsKCJjdXJyZW50IiwgQ2F0ZWdvcnkpIH4gIkN1cnJlbnQiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiRXZlciIsKSwKICAgICAgICAgUHJvZHVjdCA9IGNhc2Vfd2hlbihncmVwbCgibm9uX2VjaWciLCBDYXRlZ29yeSkgfiAiT3RoZXIgcHJvZHVjdHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiRS1jaWdhcmV0dGVzIikpICU+JQogIGRwbHlyOjpzZWxlY3QoLUNhdGVnb3J5KSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gRXN0aW1hdGUsIAogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gYFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgKSAlPiUKICAjc3ByZWFkKEVzdGltYXRlLCBgUGVyY2VudGFnZSBvZiBzdHVkZW50c2ApICU+JQogIGZpbHRlcihVc2VyPT0iRXZlciIpICU+JQogIGRwbHlyOjpyZW5hbWUoIkxvd2VyX3RlbXAiID0gVXBwZXIsCiAgICAgICAgICAgICAgICAiVXBwZXJfdGVtcCIgPSBMb3dlcikgJT4lCiAgZHBseXI6OnJlbmFtZSgiTG93ZXIiPUxvd2VyX3RlbXAsCiAgICAgICAgICAgICAgICAiVXBwZXIiPVVwcGVyX3RlbXApICU+JQogIGdncGxvdChhZXMoeD15ZWFyLHk9TWVhbiwgY29sb3I9UHJvZHVjdCkpICsKICBnZW9tX2xpbmUobGluZXR5cGU9MSkgKwogIGdlb21fbGluZXJhbmdlKGFlcyh5bWluID0gTG93ZXIsIHltYXggPSBVcHBlcikpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgxMCwgNjAsIGJ5ID0gMTApLCBsaW1pdHMgPSBjKDEwLDYwKSkgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogICAgbGFicyh0aXRsZSA9ICIlIGV2ZXIgdHJ5aW5nIG5pY290aW5lIHByb2R1Y3RzIGluY3JlYXNlcyIsCiAgICAgICAgIHkgPSAiJSBvZiBzdHVkZW50cyIpCgpwbG90Q193XzggPC0gbnl0c19kYXRhICU+JQogIGZpbHRlcigoR3JhZGUgPT0gIjgiICYgeWVhciA9PSAyMDE1KSB8CiAgICAgICAgIChHcmFkZSA9PSAiOSIgJiB5ZWFyID09IDIwMTYpIHwKICAgICAgICAgKEdyYWRlID09ICIxMCIgJiB5ZWFyID09IDIwMTcpIHwKICAgICAgICAgKEdyYWRlID09ICIxMSIgJiB5ZWFyID09IDIwMTgpIHwKICAgICAgICAgIChHcmFkZSA9PSAiMTIiICYgeWVhciA9PSAyMDE5KSAKICAgICAgICAgKSAlPiUKICAgIG11dGF0ZShlY2lnX3N1bV9ldmVyID0gc2VsZWN0KC4sIEVFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpLAogICAgICAgICAgIGVjaWdfc3VtX2N1cnJlbnQgPSBzZWxlY3QoLiwgQ0VMQ0lHVCkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSksCiAgICAgICAgICAgbm9uX2VjaWdfc3VtX2V2ZXIgPSBzZWxlY3QoLiwgc3RhcnRzX3dpdGgoIkUiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSkgJT4lCiAgICAgICAgICAgICAgIHNlbGVjdCguLC1FRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICBub25fZWNpZ19zdW1fY3VycmVudCA9IHNlbGVjdCguLCBzdGFydHNfd2l0aCgiQyIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSAlPiUKICAgICAgICAgICAgICAgc2VsZWN0KC4sLUNFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpKSAlPiUKICAgIG11dGF0ZShlY2lnX2V2ZXIgPSBjYXNlX3doZW4oZWNpZ19zdW1fZXZlciA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlY2lnX3N1bV9ldmVyID09MCB+IEZBTFNFKSwKICAgICAgICAgICBlY2lnX2N1cnJlbnQgPSBjYXNlX3doZW4oZWNpZ19zdW1fY3VycmVudCA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlY2lnX3N1bV9jdXJyZW50ID09MCB+IEZBTFNFKSwKICAgICAgICAgICBub25fZWNpZ19ldmVyID0gY2FzZV93aGVuKG5vbl9lY2lnX3N1bV9ldmVyID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbl9lY2lnX3N1bV9ldmVyID09MCB+IEZBTFNFKSwKICAgICAgICAgICBub25fZWNpZ19jdXJyZW50ID0gY2FzZV93aGVuKG5vbl9lY2lnX3N1bV9jdXJyZW50ID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbl9lY2lnX3N1bV9jdXJyZW50ID09MCB+IEZBTFNFKSkgJT4lCiAgYXNfc3VydmV5X2Rlc2lnbihzdHJhdGEgPSBzdHJhdHVtLCBpZHMgPSBwc3UsIHdlaWdodCAgPSBmaW53Z3QpICU+JQogICAgZ3JvdXBfYnkoeWVhcikgJT4lCiAgc3VtbWFyaXNlKGVjaWdfZXZlcl95ZWFyID0gc3VydmV5X21lYW4oZWNpZ19ldmVyLCB2YXJ0eXBlID0gImNpIiwgbmEucm09VFJVRSksCiAgICAgICAgICAgIGVjaWdfY3VycmVudF95ZWFyID0gc3VydmV5X21lYW4oZWNpZ19jdXJyZW50LCB2YXJ0eXBlID0gImNpIiwgbmEucm09VFJVRSksCiAgICAgICAgICAgIG5vbl9lY2lnX2V2ZXJfeWVhciA9IHN1cnZleV9tZWFuKG5vbl9lY2lnX2V2ZXIsIHZhcnR5cGUgPSAiY2kiLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICAgbm9uX2VjaWdfY3VycmVudF95ZWFyID0gc3VydmV5X21lYW4obm9uX2VjaWdfY3VycmVudCwgdmFydHlwZSA9ICJjaSIsIG5hLnJtPVRSVUUpKSAlPiUKICBtdXRhdGVfYXQodmFycygteWVhciksICIqIiwgMTAwKSAlPiUKICBkcGx5cjo6c2VsZWN0KHllYXIsCiAgICAgICAgICAgICAgICBlY2lnX2V2ZXJfeWVhciwKICAgICAgICAgICAgICAgIGVjaWdfY3VycmVudF95ZWFyLAogICAgICAgICAgICAgICAgbm9uX2VjaWdfZXZlcl95ZWFyLAogICAgICAgICAgICAgICAgbm9uX2VjaWdfY3VycmVudF95ZWFyLAogICAgICAgICAgICAgICAgY29udGFpbnMoImxvdyIpLAogICAgICAgICAgICAgICAgY29udGFpbnMoInVwcCIpKSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IC15ZWFyLCBuYW1lc190byA9ICJDYXRlZ29yeSIsIHZhbHVlc190byA9ICJQZXJjZW50YWdlIG9mIHN0dWRlbnRzIiklPiUKICAgICMgZ2F0aGVyKGtleT1DYXRlZ29yeSwKICAgICMgICAgICAgIHZhbHVlPWBQZXJjZW50YWdlIG9mIHN0dWRlbnRzYCwKICAgICMgICAgICAgIC15ZWFyKSAlPiUKICAgIG11dGF0ZShFc3RpbWF0ZSA9IGNhc2Vfd2hlbihncmVwbCgiX2xvdyIsIENhdGVnb3J5KSB+ICJMb3dlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JlcGwoIl91cHAiLCBDYXRlZ29yeSkgfiAiVXBwZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiTWVhbiIpLAogICAgICAgICBVc2VyID0gY2FzZV93aGVuKGdyZXBsKCJldmVyIiwgQ2F0ZWdvcnkpIH4gIkV2ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGdyZXBsKCJjdXJyZW50IiwgQ2F0ZWdvcnkpIH4gIkN1cnJlbnQiKSwKICAgICAgICAgUHJvZHVjdCA9IGNhc2Vfd2hlbihncmVwbCgibm9uX2VjaWciLCBDYXRlZ29yeSkgfiAiT3RoZXIgcHJvZHVjdHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiRS1jaWdhcmV0dGVzIikpICU+JQogIGRwbHlyOjpzZWxlY3QoLUNhdGVnb3J5KSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gRXN0aW1hdGUsIAogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gYFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgKSAlPiUKICAjc3ByZWFkKEVzdGltYXRlLCBgUGVyY2VudGFnZSBvZiBzdHVkZW50c2ApICU+JQogICAgZ2dwbG90KGFlcyh4PXllYXIseT1NZWFuLCBjb2xvcj1Qcm9kdWN0KSkgKwogIGdlb21fbGluZShhZXMobGluZXR5cGU9VXNlcikpICsKICBnZW9tX2xpbmVyYW5nZShhZXMoeW1pbiA9IExvd2VyLCB5bWF4ID0gVXBwZXIpKSArIAogIHNjYWxlX2xpbmV0eXBlX21hbnVhbCh2YWx1ZXMgPSBjKDIsMSkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDYwLCBieSA9IDEwKSwgbGltaXRzID0gYygwLDYwKSkgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogICAgbGFicyh0aXRsZSA9ICJFLWNpZ2FyZXR0ZSB1c2Ugc3VycGFzc2VzIHVzZSBvZiBvdGhlciBuaWNvdGluZSBwcm9kdWN0cyIsCiAgICAgICAgIHkgPSAiJSBvZiBzdHVkZW50cyIpCgp0aXRsZV93XzggPC0gZ2dkcmF3KCkgKyAKICBkcmF3X2xhYmVsKAogICAgZXhwcmVzc2lvbigiQW1vbmcifjhedGh+ImdyYWRlcnMgaW4gMjAxNSwgaGF2ZSB2YXBpbmcgcmF0ZXMgcG9zc2libHkgaW5mbHVlbmNlZCB0b2JhY2NvL25pY290aW5lIHVzZT8iKSwKICAgIGZvbnRmYWNlID0gJ2JvbGQnLAogICAgc2l6ZT0xNCwKICAgIHggPSAwLAogICAgaGp1c3QgPSAwCiAgKSArCiAgdGhlbWUoCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLCAwLCAwLCAwKQogICkKCnBsb3RzQV93XzggPC0gcGxvdF9ncmlkKHBsb3RBX3dfOCwKICAgICAgICAgICAgICAgICAgICAgICAgcmVsX3dpZHRocyA9IGMoMSksCiAgICAgICAgICAgICAgICAgICAgICAgIGFsaWduID0gInYiLAogICAgICAgICAgICAgICAgICAgICAgICBheGlzID0gImJ0IikKCnBsb3RzQkNfd184IDwtIHBsb3RfZ3JpZChwbG90Ql93XzgsCiAgICAgICAgICAgICAgICAgICAgICAgICBwbG90Q193XzgsCiAgICAgICAgICAgICAgICAgICAgICAgICByZWxfd2lkdGhzID0gYygxLDEpLAogICAgICAgICAgICAgICAgICAgICAgICAgYXhpcyA9ICJidCIpCgpsZWdlbmRfd184IDwtIGdldF9sZWdlbmQocGxvdEJfd184ICsKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQuZGlyZWN0aW9uID0gImhvcml6b250YWwiKSkKCmZpZ3VyZV93XzggPC0gcGxvdF9ncmlkKHRpdGxlX3dfOCwKICAgICAgICAgICAgICAgICAgICAgICAgcGxvdHNBX3dfOCwKICAgICAgICAgICAgICAgICAgICAgICAgcGxvdHNCQ193XzgsCiAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZF93XzgsCiAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAxLAogICAgICAgICAgICAgICAgICAgICAgICByZWxfaGVpZ2h0cyA9IGMoMC4xLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAwLjEpLAogICAgICAgICAgICAgICAgICAgICAgICBzY2FsZSA9IDEuMAopCgpmaWd1cmVfd184CmBgYAoKIyMjIEZpbmFsIEZpZ3VyZQoKYGBge3J9CnRpdGxlX2ZpbmFsIDwtIGdnZHJhdygpICsKICBkcmF3X2xhYmVsKAogICAgZXhwcmVzc2lvbigiSGF2ZSB2YXBpbmcgcmF0ZXMgcG9zc2libHkgaW5mbHVlbmNlZCB0b2JhY2NvL25pY290aW5lIHVzZT8iKSwKICAgIGZvbnRmYWNlID0gJ2JvbGQnLAogICAgc2l6ZT0xNiwKICAgIHggPSAwLjUpICsKICB0aGVtZSgKICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKDAsIDAsIDAsIDApCiAgKQoKc3VidGl0bGVfdXdfZmluYWwgPC0gZ2dkcmF3KCkgKyAKICBkcmF3X2xhYmVsKAogICAgZXhwcmVzc2lvbih+Nl50aH4iLSJ+MTJedGh+ImdyYWRlcnMsIHVud2VpZ2h0ZWQiKSwKICAgIHNpemU9MTIsCiAgICB4ID0gMC41KSArCiAgdGhlbWUoCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLCAwLCAwLCAwKQogICkKCnN1YnRpdGxlX3dfZmluYWwgPC0gZ2dkcmF3KCkgKyAKICBkcmF3X2xhYmVsKAogICAgZXhwcmVzc2lvbih+Nl50aH4iLSJ+MTJedGh+ImdyYWRlcnMsIHdlaWdodGVkIiksCiAgICBmb250ZmFjZSA9ICdib2xkJywKICAgIHNpemU9MTIsCiAgICB4ID0gMC41KSArCiAgdGhlbWUoCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLCAwLCAwLCAwKQogICkKCnN1YnRpdGxlX3dfOF9maW5hbCA8LSBnZ2RyYXcoKSArIAogIGRyYXdfbGFiZWwoCiAgICBleHByZXNzaW9uKH44XnRofiJncmFkZXJzIGluIDIwMTUsIHdlaWdodGVkIiksCiAgICBmb250ZmFjZSA9ICdib2xkJywKICAgIHNpemU9MTIsCiAgICB4ID0gMC41KSArCiAgdGhlbWUoCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLCAwLCAwLCAwKQogICkKCnN1YnRpdGxlX2ZpbmFsIDwtIHBsb3RfZ3JpZChzdWJ0aXRsZV91d19maW5hbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1YnRpdGxlX3dfZmluYWwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJ0aXRsZV93XzhfZmluYWwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuY29sID0gMykKCnBsb3RzQV90aXRsZV9maW5hbCA8LSBnZ2RyYXcoKSArIAogIGRyYXdfbGFiZWwoCiAgICBleHByZXNzaW9uKCJQcmV2YWxlbmNlIG9mIGUtY2lnYXJldHRlIHVzZSBieSB1c2VyIHR5cGUiKSwKICAgIHNpemU9MTQsCiAgICB4ID0gMC41KSArCiAgdGhlbWUoCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLCAwLCAwLCAwKQogICkKCnBsb3RzQV9maW5hbCA8LSBwbG90X2dyaWQocGxvdEFfdXcgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF9ibGFuaygpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90QV93ICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdEFfd184ICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgYWxpZ24gPSAidiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcyA9ICJidCIpCgpwbG90c0JfdGl0bGVfZmluYWwgPC0gZ2dkcmF3KCkgKyAKICBkcmF3X2xhYmVsKAogICAgZXhwcmVzc2lvbigiUHJldmFsZW5jZSBvZiBldmVyIHVzZSBieSBwcm9kdWN0IHR5cGUiKSwKICAgIHNpemU9MTQsCiAgICB4ID0gMC41KSArCiAgdGhlbWUoCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLCAwLCAwLCAwKQogICkKCnBsb3RzQl9maW5hbCA8LSBwbG90X2dyaWQocGxvdEJfdXcgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF9ibGFuaygpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90Ql93ICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdEJfd184ICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgYWxpZ24gPSAidiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcyA9ICJidCIpCgpwbG90c0NfdGl0bGVfZmluYWwgPC0gZ2dkcmF3KCkgKyAKICBkcmF3X2xhYmVsKAogICAgZXhwcmVzc2lvbigiUHJldmFsZW5jZSBvZiBuaWNvdGluZSBwcm9kdWN0IHVzZSBieSBwcm9kdWN0ICYgdXNlciB0eXBlIiksCiAgICBzaXplPTE0LAogICAgeCA9IDAuNSkgKwogIHRoZW1lKAogICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4oMCwgMCwgMCwgMCkKICApCgpwbG90c0NfZmluYWwgPC0gcGxvdF9ncmlkKHBsb3RDX3V3ICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdENfdyArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpLAogICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3RDX3dfOCArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpLAogICAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAzLAogICAgICAgICAgICAgICAgICAgICAgICAgIGFsaWduID0gInYiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMgPSAiYnQiKQoKbGVnZW5kX2ZpbmFsIDwtIGdldF9sZWdlbmQocGxvdEJfdyArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIikpCgpmaW5hbF9wbG90IDwtIHBsb3RfZ3JpZCh0aXRsZV9maW5hbCwKICAgICAgICAgIHBsb3RzQV90aXRsZV9maW5hbCwKICAgICAgICAgIHN1YnRpdGxlX2ZpbmFsLAogICAgICAgICAgcGxvdHNBX2ZpbmFsLAogICAgICAgICAgcGxvdHNCX3RpdGxlX2ZpbmFsLAogICAgICAgICAgc3VidGl0bGVfZmluYWwsCiAgICAgICAgICBwbG90c0JfZmluYWwsCiAgICAgICAgICBwbG90c0NfdGl0bGVfZmluYWwsCiAgICAgICAgICBzdWJ0aXRsZV9maW5hbCwKICAgICAgICAgIHBsb3RzQ19maW5hbCwKICAgICAgICAgIGxlZ2VuZF9maW5hbCwKICAgICAgICAgIG5jb2wgPSAxLAogICAgICAgICAgcmVsX2hlaWdodHMgPSBjKDAuMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAwLjIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgMC4xLAogICAgICAgICAgICAgICAgICAgICAgICAgIDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgMC4yLAogICAgICAgICAgICAgICAgICAgICAgICAgIDAuMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAxLAogICAgICAgICAgICAgICAgICAgICAgICAgIDAuMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAwLjEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAwLjEpKQoKZmluYWxfcGxvdApgYGAKCmBgYHtyLCBlY2hvPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpnZ3NhdmUoImZpbmFsX3Bsb3QucG5nIikKYGBgCgojIyAqKlN1Z2dlc3RlZCBIb21ld29yayoqCioqKiAKCjxzdHlsZT4KZGl2LmJsdWUgeyBiYWNrZ3JvdW5kLWNvbG9yOiNlNmYwZmY7IGJvcmRlci1yYWRpdXM6IDVweDsgcGFkZGluZzogMjBweDt9Cjwvc3R5bGU+CjxkaXYgY2xhc3MgPSAiYmx1ZSI+CgorIEFwcGx5IHN1cnZleSB3ZWlnaHRzIHRvIG9uZSBvZiB0aGUgZmlndXJlcyBwcm9kdWNlZCBpbiB0aGlzIGNhc2Ugc3R1ZHkgaW4gd2hpY2ggd2VpZ2h0ZWQgZXN0aW1hdGVzIHdlcmUgbm90IHByb2R1Y2VkLiBJbmNsdWRlIGVycm9yIGJhcnMgaW4gdGhlIHVwZGF0ZWQgZmlndXJlLgogICAgKyBEb2VzIHRoZSBmaWd1cmUgY2hhbmdlIGFmdGVyIHRoZSBhcHBsaWNhdGlvbiBvZiBzdXJ2ZXkgd2VpZ2h0cz8KICAgICsgSWYgc28sIGRlc2NyaWJlIGhvdy4gCisgUmVwcm9kdWNlIGBmaW5hbF9wbG90YCBhYm92ZSBmb3IgYSBkaWZmZXJlbnQgY29ob3J0IG9mIHlvdXIgY2hvaWNlLgoKPC9kaXY+CgojIyMgTm90ZXMKCkV2ZXIgYW5kIGN1cnJlbnQgdmFyaWFibGVzIGFyZSBsaW1pdGVkIHRvIHRob3NlIHNoYXJlZCBieSBhbGwgeWVhcnMgb2YgZGF0YSBpbmNsdWRlZCBpbiB0aGlzIGNhc2Ugc3R1ZHkuCgpgYGB7ciwgZWNobz1GQUxTRX0Ka25pdF90aW1lX2VuZCA8LSBTeXMudGltZSgpCmBgYAoKYGBge3IsIGVjaG89RkFMU0V9CmtuaXRfdGltZSA8LSBrbml0X3RpbWVfZW5kIC0ga25pdF90aW1lX3N0YXJ0CmtuaXRfdGltZV9tZXNzYWdlIDwtIHBhc3RlKCJLbml0IHRpbWU6IiwKICAgICAgcm91bmQoYXMubnVtZXJpYyhrbml0X3RpbWUpICwzKSwKICAgICAgdW5pdHMoa25pdF90aW1lKQogICAgICApCmBgYAoKPHAgc3R5bGU9ImNvbG9yOnJlZCI+TmV3IGNvZGU6IGByIGtuaXRfdGltZV9tZXNzYWdlYC4gUHJldmlvdXMgY29kZTogfiAzIG0uIDwvcD4KCiMjIyBQcm9ibGVtcwoKSSBoYWQgZGlmZmljdWx0eSBwcm9kdWNpbmcgYSBwbG90IHRoYXQgc3VjY2luY3RseSBwcmVzZW50ZWQgYSB0cmVuZC4gSXQncyB2ZXJ5IGVhc3kgdG8gcHJvZHVjZSBwbG90cyB0aGF0IGFyZSB2ZXJ5IHVzZWZ1bCBvbmNlIG9uZSBpcyBmYW1pbGlhciB3aXRoIHRoZSBkYXRhLiBTb21lIHBsb3RzLCBob3dldmVyLCBjYW5ub3Qgc3RhbmQgYWxvbmUgYW5kIG5lZWQgYWRkaXRpb25hbCBjb250ZXh0IHRvIGJlIGNsZWFyIGZvciB0aG9zZSB3aXRob3V0IHByaW9yIGtub3dsZWRnZSBvZiB0aGUgZGF0YS4gV2hlbiBJIGZpcnN0IHNoYXJlZCBhIHBsb3QgSSBoYWQgYmVlbiB3b3JraW5nIG9uIHdpdGggb3RoZXJzLCBpdCBiZWNhbWUgY2xlYXIgdGhhdCBpbiBteSBlZmZvcnQgdG8gcHJlc2VudCBhIGNvbXBsaWNhdGVkIGlkZWEgYnJpZWZseSBJIGhhZCBsZWZ0IG91dCBpbmZvcm1hdGlvbiB0aGF0IHdvdWxkIG1ha2UgdGhlIHRyZW5kIGVhc2lseSBpbnRlcnByZXRhYmxlLiBUbyBzb2x2ZSB0aGlzIGlzc3VlLCBJIGJlZ2FuIHRvIHByZXNlbnQgdmlzdWFsaXphdGlvbnMgb2YgdGhlIGRhdGEgYWxvbmdzaWRlIG15IG9yaWdpbmFsIHBsb3QuIFRoZSBmaW5hbCBmaWd1cmUgSSBjcmVhdGVkIGNvbnRhaW5lZCBzZXZlcmFsIGFkZGl0aW9uYWwgcGxvdHMsIGVhY2ggcHJlc2VudGluZyB0aGUgc2FtZSB0cmVuZCBhdCBhIGRpZmZlcmVudCBsZXZlbCB0aGFuIG15IGluaXRpYWwgcGxvdC4KCk15ICJjZW50ZXJwaWVjZSIgcGxvdCBpcyB0aGUgbWlkZGxlIHBsb3QgaW4gYGZpbmFsX3Bsb3RgLiBUaGUgOCBwbG90cyBhcm91bmQgaXQgaGVscCBwcm92aWRlIGEgdmVyeSBjbGVhciBwaWN0dXJlIG9mIHdoYXQgaXMgZ29pbmcgb24gaW4gdGhlIFVTIHdpdGggcmVnYXJkcyB0byBlLWNpZ2FyZXR0ZSB1c2UgYW5kIG5pY290aW5lIHByb2R1Y3QgdXNlIGF0IGxhcmdlLiBPbiBpdHMgb3duLCBpdCdzIGRpZmZpY3VsdCB0byB1bmRlcnN0YW5kIHRoZSB0cmVuZHMgaW4gdGhlIFVTIGFuZCBob3cgaW1wb3J0YW50IHRoZSB3ZWlnaHRpbmcgc2NoZW1lIGlzIGZvciBpbmZlcmVuY2UuIE9uY2UgeW91IGFkZCB0aGUgbGVmdCBhbmQgcmlnaHQgY29sdW1ucywgaXQncyBjbGVhciB3aGF0IGlzIGdvaW5nIG9uLiAKCgoKIyMgKipEYXRhIEFuYWx5c2lzKioKKioqIAoKIyMjICoqY29udGVudCBoZWFkZXIqKgoqKiogCgoKCiMjICoqU3VtbWFyeSoqCioqKiAKCgoKIyMgKipIZWxwZnVsIExpbmtzKioKKioqIAoKcmV2aWV3IG9mIFt0aWR5bW9kZWxzXShodHRwczovL3J2aWV3cy5yc3R1ZGlvLmNvbS8yMDE5LzA2LzE5L2EtZ2VudGxlLWludHJvLXRvLXRpZHltb2RlbHMvKXt0YXJnZXQ9Il9ibGFuayJ9IAoKZ3VpZGUgZm9yIFtwcmVwcm9jZXNzaW5nIHdpdGggcmVjaXBlc10oaHR0cDovL3d3dy5yZWJlY2NhYmFydGVyLmNvbS9ibG9nLzIwMTktMDYtMDZfcHJlX3Byb2Nlc3NpbmcvKQoKCiMjICoqU2Vzc2lvbiBpbmZvKioKKioqCgpgYGB7cn0Kc2Vzc2lvbkluZm8oKQpgYGA=